ACM-ICPC 2018 焦作赛区网络预赛 E - Jiu Yuan Wants to Eat

You ye Jiu yuan is the daughter of the Great GOD Emancipator. And when she becomes an adult, she will be queen of Tusikur, so she wanted to travel the world while she was still young. In a country, she found a small pub called Whitehouse. Just as she was about to go in for a drink, the boss Carola appeared. And ask her to solve this problem or she will not be allowed to enter the pub. The problem description is as follows:

There is a tree with nn nodes, each node ii contains weight a[i], the initial value of a[i] is 0. The root number of the tree is 1. Now you need to do the following operations:

1)1) Multiply all weight on the path from u to v by x

2)2) For all weight on the path from u to v, increasing x to them

3)3) For all weight on the path from u to v, change them to the bitwise NOT of them

4)4) Ask the sum of the weight on the path from u to v

The answer modulo 2^64.

Jiu Yuan is a clever girl, but she was not good at algorithm, so she hopes that you can help her solve this problem. 

The bitwise NOT is a unary operation that performs logical negation on each bit, forming the ones' complement of the given binary value. Bits that are 0 become 1, and those that are 1 become 0. For example:

NOT 0111 (decimal 7) = 1000 (decimal 8)

NOT 10101011 = 01010100

Input

The input contains multiple groups of data.

For each group of data, the first line contains a number of nn, and the number of nodes.

The second line contains (n−1) integers bi​, which means that the father node of node(i+1) is bi​.

The third line contains one integer mm, which means the number of operations,

The next mm lines contain the following four operations:

At first, we input one integer opt

1) If opt is 1, then input 3 integers u, v, x which means multiply all weight on the path from u to v by x.

2) If opt is 2, then input 3 integers u, v, x, which means for all weight on the path from u to v, increasing x to them.

2) If opt is 3, then input 2 integers  u, v which means for all weight on the path from u to v, change them to the bitwise NOT of them

4)If opt is 4, then input 2 integers u, v and ask the sum of the weights on the path from u to v

1 ≤ n,m,u,v ≤ 10^5

1 ≤ x < 2^64

Output

For each operation 4, output the answer.

样例输入

7
1 1 1 2 2 4
5
2 5 6 1
1 1 6 2
4 5 6
3 5 2
4 2 2
2
1
4
3 1 2
4 1 2
3 1 1
4 1 1

样例输出

5
18446744073709551613
18446744073709551614
0

题意

给你一棵树进行树链剖分后进行4种操作:

1 u v x     u到v上的每一个节点乘x

2 u v x     u到v上的每一个节点加x

3 u v        u到v上的每一个节点取反

4 u v        输出u到v上的节点的权值和mod 2^64

1、2、4操作都是树链剖分+线段树维护多个懒惰标记的常规操作,但操作4由于是对2^64方进行取模,并且加和乘的x都大于1(保证权值不会出现负数),因此我们可以用unsigned long long 来维护,这样在在数据溢出的时候会自动对2^64方取模,也因此操作3便十分方便

由位反的定义可知

~x = 2^64 - 1 - x

由于ull导致加上的2^64方自动溢出,原式在ull的意义下,等价于

~x = -1 - x

因此对x取反等价于x先乘-1再-1

#include <iostream>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <map>
#include <algorithm>
#include <queue>
#include <set>
#include <cmath>
#include <sstream>
#include <stack>
#include <fstream>
#include <ctime>
#pragma warning(disable:4996);
#define lson rt << 1
#define rson rt << 1|1
#define mid  ((l + r) >> 1)
#define Lson l, mid, lson
#define Rson mid+1,r,rson
#define mem(sx,sy) memset(sx,sy,sizeof(sx))
//typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-8;
const double PI = acos(-1.0);
//const ll llINF = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;
using namespace std;
//
int n;
const int maxn = 2e5 + 10;
struct edge {
	int to, next;
}edges[maxn];
int head[maxn], cnt;
void addedge(int u, int v) {
	edges[++cnt].to = v;
	edges[cnt].next = head[u];
	head[u] = cnt;
}
//
int son[maxn], tid[maxn], fa[maxn], dep[maxn], siz[maxn], top[maxn], rnk[maxn], cnt2;
void dfs1(int u, int f, int d) {
	dep[u] = d;
	fa[u] = f;
	siz[u] = 1;
	for (int i = head[u]; i != -1; i = edges[i].next) {
		int v = edges[i].to;
		if (v != fa[u]) {
			dfs1(v, u, d + 1); 
			siz[u] += siz[v];
			if (son[u] == -1 || siz[v] > siz[son[u]])
				son[u] = v;
		}
	}
}
void dfs2(int u, int topf) {
	tid[u] = ++cnt2;
	rnk[cnt2] = u;
	top[u] = topf;
	if (son[u] == -1)return;
	dfs2(son[u], topf);
	for (int i = head[u]; i != -1; i = edges[i].next) {
		int v = edges[i].to;
		if (v != fa[u] && v != son[u])
			dfs2(v, v);
	}
}
//
ull sum[maxn << 2], add[maxn << 2], mul[maxn << 2];
void pushup(int rt) {
	sum[rt] = sum[rson] + sum[lson];
}
void pushdown(int m, int rt) {
	add[lson] = add[lson] * mul[rt] + add[rt];
	add[rson] = add[rson] * mul[rt] + add[rt];
	mul[lson] = mul[lson] * mul[rt];
	mul[rson] = mul[rson] * mul[rt];
	sum[lson] = sum[lson] * mul[rt] + add[rt] * (m - (m >> 1));
	sum[rson] = sum[rson] * mul[rt] + add[rt] * (m >> 1);
	add[rt] = 0; mul[rt] = 1;
}
void build(int l, int r, int rt) {
	add[rt] = 0; mul[rt] = 1;
	if (l == r) {
		sum[rt] = 0;
		return;
	}
	build(Lson); build(Rson);
	pushup(rt);
}
void update(int L,int R, ull c, int op, int l, int r, int rt) {
	if (L <= l && R >= r) {
		if (op == 1) {
			sum[rt] = sum[rt] * c;
			add[rt] = add[rt] * c;
			mul[rt] = mul[rt] * c;
		}
		else if (op == 2) {
			sum[rt] = sum[rt] + (ull)c*(r - l + 1);
			add[rt] = add[rt] + c;
		}
		else if (op == 3) {
			sum[rt] = sum[rt] * (-1) - (ull)(r - l + 1);
			add[rt] = add[rt] * (-1) - 1;
			mul[rt] = mul[rt] * (-1);
		}
		return;
	}
	pushdown(r - l + 1, rt);
	if (L <= mid) update(L, R, c, op, Lson);
	if (R > mid)  update(L, R, c, op, Rson);
	pushup(rt);
}
ull query(int L, int R, int l, int r, int rt) {
	if (L <= l && R >= r) {
		return sum[rt];
	}
	pushdown(r - l + 1, rt);
	ull ret = 0;
	if (L <= mid) ret += query(L, R, Lson);
	if (R > mid)  ret += query(L, R, Rson);
	return ret;
}
//
void cover(int x, int y, ull v, int op) {
	int fx = top[x], fy = top[y];
	while (fx != fy) {
		if (dep[fx] < dep[fy]) swap(fx, fy), swap(x, y);
		update(tid[fx], tid[x], v, op, 1, n, 1);
		x = fa[fx]; fx = top[x];
	}
	if (dep[x] < dep[y]) swap(x, y);
	update(tid[y], tid[x], v, op, 1, n, 1);
}
ull ask(int x, int y) {
	int fx = top[x], fy = top[y];
	ull ans = 0;
	while (fx != fy) {
		if (dep[fx] < dep[fy]) swap(fx, fy), swap(x, y);
		ans += query(tid[fx], tid[x], 1, n, 1);
		x = fa[fx]; fx = top[x];
	}
	if (dep[x] < dep[y]) swap(x, y);
	ans += query(tid[y], tid[x], 1, n, 1);
	return ans;
}
//
void init() {
	cnt = cnt2 = 0;
	mem(head, -1);
	mem(son, -1);
}
int main() {
	while (~scanf("%d", &n)) {
		init();
		for (int i = 2, x; i <= n; i++) {
			scanf("%d", &x);
			addedge(x, i);//,addedge(i, x);
		}
		dfs1(1, 0, 1);
		dfs2(1, 1);
		build(1, n, 1);
		int Q; ull v;
		scanf("%d", &Q);
		for (int i = 0, op, l, r; i < Q; i++) {
			scanf("%d%d%d", &op, &l, &r);
			if (op == 1 || op == 2) {
				scanf("%llu", &v);
				cover(l, r, v, op);
			}
			else if (op == 3) {
				cover(l, r, 0, op);
			}
			else {
				printf("%llu\n", ask(l, r));
			}
		}
	}
}

稍微改进了下树链剖分的模板

#include <iostream>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <map>
#include <algorithm>
#include <queue>
#include <set>
#include <cmath>
#include <sstream>
#include <stack>
#include <fstream>
#include <ctime>
#pragma warning(disable:4996);
#define lson rt << 1
#define rson rt << 1|1
#define mid  ((l + r) >> 1)
#define Lson l, mid, lson
#define Rson mid+1,r,rson
#define mem(sx,sy) memset(sx,sy,sizeof(sx))
//typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-8;
const double PI = acos(-1.0);
//const ll llINF = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;
using namespace std;
//
int n;
const int maxn = 2e5 + 10;
struct edge {
	int to, next;
}edges[maxn];
int head[maxn], cnt;
void addedge(int u, int v) {
	edges[++cnt].to = v;
	edges[cnt].next = head[u];
	head[u] = cnt;
}
//
int son[maxn], tid[maxn], fa[maxn], dep[maxn], siz[maxn], top[maxn], rnk[maxn], cnt2;
void dfs1(int u, int f, int d) {
	dep[u] = d;
	fa[u] = f;
	siz[u] = 1;
	for (int i = head[u]; i != -1; i = edges[i].next) {
		int v = edges[i].to;
		if (v != fa[u]) {
			dfs1(v, u, d + 1);
			siz[u] += siz[v];
			if (son[u] == -1 || siz[v] > siz[son[u]])
				son[u] = v;
		}
	}
}
void dfs2(int u, int topf) {
	tid[u] = ++cnt2;
	rnk[cnt2] = u;
	top[u] = topf;
	if (son[u] == -1)return;
	dfs2(son[u], topf);
	for (int i = head[u]; i != -1; i = edges[i].next) {
		int v = edges[i].to;
		if (v != fa[u] && v != son[u])
			dfs2(v, v);
	}
}
//
ull sum[maxn << 2], add[maxn << 2], mul[maxn << 2];
void pushup(int rt) {
	sum[rt] = sum[rson] + sum[lson];
}
void pushdown(int m, int rt) {
	add[lson] = add[lson] * mul[rt] + add[rt];
	add[rson] = add[rson] * mul[rt] + add[rt];
	mul[lson] = mul[lson] * mul[rt];
	mul[rson] = mul[rson] * mul[rt];
	sum[lson] = sum[lson] * mul[rt] + add[rt] * (m - (m >> 1));
	sum[rson] = sum[rson] * mul[rt] + add[rt] * (m >> 1);
	add[rt] = 0; mul[rt] = 1;
}
void build(int l, int r, int rt) {
	add[rt] = 0; mul[rt] = 1;
	if (l == r) {
		sum[rt] = 0;
		return;
	}
	build(Lson); build(Rson);
	pushup(rt);
}
void update(int L, int R, ull c, int op, int l, int r, int rt) {
	if (L <= l && R >= r) {
		if (op == 1) {
			sum[rt] = sum[rt] * c;
			add[rt] = add[rt] * c;
			mul[rt] = mul[rt] * c;
		}
		else if (op == 2) {
			sum[rt] = sum[rt] + (ull)c*(r - l + 1);
			add[rt] = add[rt] + c;
		}
		else if (op == 3) {
			sum[rt] = sum[rt] * (-1) - (ull)(r - l + 1);
			add[rt] = add[rt] * (-1) - 1;
			mul[rt] = mul[rt] * (-1);
		}
		return;
	}
	pushdown(r - l + 1, rt);
	if (L <= mid) update(L, R, c, op, Lson);
	if (R > mid)  update(L, R, c, op, Rson);
	pushup(rt);
}
ull query(int L, int R, int l, int r, int rt) {
	if (L <= l && R >= r) {
		return sum[rt];
	}
	pushdown(r - l + 1, rt);
	ull ret = 0;
	if (L <= mid) ret += query(L, R, Lson);
	if (R > mid)  ret += query(L, R, Rson);
	return ret;
}
//
int getLength(int a, int b) {
	int ret = 0;
	while (top[a] != top[b]) {
		if (dep[top[a]] < dep[top[b]]) swap(a, b);
		ret += tid[a] - tid[top[a]] + 1;
		a = fa[top[a]];
	}
	if (dep[a] > dep[b]) swap(a, b);
	return ret + tid[b] - tid[a] + 1;
}


void cover(int a, int b, ull v, int op) {
	while (top[a] != top[b]) {
		if (dep[top[a]] < dep[top[b]]) swap(a, b);
		update(tid[top[a]], tid[a], v, op, 1, n, 1);
		a = fa[top[a]];
	}
	if (dep[a] > dep[b]) swap(a, b);
	update(tid[a], tid[b], v, op, 1, n, 1);
}
ull ask(int a, int b) {
	ull ans = 0;
	while (top[a] != top[b]) {
		if (dep[top[a]] < dep[top[b]]) swap(a, b);
		ans += query(tid[top[a]], tid[a], 1, n, 1);
		a = fa[top[a]];
	}
	if (dep[a] > dep[b]) swap(a, b);
	ans += query(tid[a], tid[b], 1, n, 1);
	return ans;
}
//
void init() {
	cnt = cnt2 = 0;
	mem(head, -1);
	mem(son, -1);
}
int main() {
	while (~scanf("%d", &n)) {
		init();
		for (int i = 2, x; i <= n; i++) {
			scanf("%d", &x);
			addedge(x, i);//,addedge(i, x);
		}
		dfs1(1, 0, 1);
		dfs2(1, 1);
		build(1, n, 1);
		int Q; ull v;
		scanf("%d", &Q);
		for (int i = 0, op, l, r; i < Q; i++) {
			scanf("%d%d%d", &op, &l, &r);
			if (op == 1 || op == 2) {
				scanf("%llu", &v);
				cover(l, r, v, op);
			}
			else if (op == 3) {
				cover(l, r, 0, op);
			}
			else {
				printf("%llu\n", ask(l, r));
			}
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_23502651/article/details/82721555