Description
给定一棵树和若干次操作,树上节点的权值一开始都是0,要求完成如下操作:
令x,y两点间路径上点的点权都乘上一个数
令x,y两点间路径上点的点权都加上一个数
令x,y两点间路径上点的点权都按位取反(~)
查询两点间路径上点的点权之和
所有答案均对$2^{64}$取模
Solution
树链剖分的题目。
关于对$2^{64}$取模,我们不妨将数组定为unsigned long long类型,这样自然溢出就实现了对这个数的取模。
关于前两个操作我们维护两个标记即可完成,
关于对第三个操作,即按位取反操作,我们不妨思考一下按位取反的实现过程,即~x=1111111...1-x,也就是我们将这个操作转换成*(-1)+unsigned long long的最大值即可
Code
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef unsigned long long ll; 4 struct node { 5 int next, to; 6 } e[200010 << 1]; 7 int num, head[200010]; 8 inline void add(int from, int to) { 9 e[++num].next = head[from]; 10 e[num].to = to; 11 head[from] = num; 12 } 13 int top[200010], fa[200010], dep[200010], size[200010], son[200010], dfn[200010], cnt; 14 void dfs1(int now, int f, int d) { 15 dep[now] = d; 16 fa[now] = f; 17 size[now] = 1; 18 for (register int i = head[now]; i; i = e[i].next) 19 if (e[i].to != f) { 20 dfs1(e[i].to, now, d + 1); 21 size[now] += size[e[i].to]; 22 if (size[son[now]] < size[e[i].to]) son[now] = e[i].to; 23 } 24 } 25 void dfs2(int now, int f) { 26 top[now] = f; 27 dfn[now] = ++cnt; 28 if (son[now]) dfs2(son[now], f); 29 for (register int i = head[now]; i; i = e[i].next) 30 if (e[i].to != son[now] && e[i].to != fa[now]) dfs2(e[i].to, e[i].to); 31 } 32 ll sum[200010 << 2]; 33 ll addtag[200010 << 2]; 34 ll addmul[200010 << 2]; 35 int n; 36 void build(int now, int l, int r) { 37 sum[now] = addtag[now] = 0; 38 addmul[now] = 1; 39 if (l == r) return ; 40 int mid = l + r >> 1; 41 build(now << 1, l, mid); 42 build(now << 1 | 1, mid + 1, r); 43 } 44 void pushup(int now) { 45 sum[now] = sum[now << 1] + sum[now << 1 | 1]; 46 } 47 void pushdown(int now, ll l, ll r) { 48 if (addmul[now] != 1) { 49 sum[now << 1] *= addmul[now]; 50 addmul[now << 1] *= addmul[now]; 51 addtag[now << 1] *= addmul[now]; 52 sum[now << 1 | 1] *= addmul[now]; 53 addmul[now << 1 | 1] *= addmul[now]; 54 addtag[now << 1 | 1] *= addmul[now]; 55 addmul[now] = 1; 56 } 57 if (addtag[now]) { 58 sum[now << 1] += addtag[now] * l; 59 addtag[now << 1] += addtag[now]; 60 sum[now << 1 | 1] += addtag[now] * r; 61 addtag[now << 1 | 1] += addtag[now]; 62 addtag[now] = 0; 63 } 64 } 65 void updateadd(int now, int l, int r, int x, int y, ll val) { 66 if (x <= l && r <= y) { 67 sum[now] += val * (r - l + 1); 68 addtag[now] += val; 69 return ; 70 } 71 int mid = l + r >> 1; 72 pushdown(now, mid - l + 1, r - mid); 73 if (x <= mid) updateadd(now << 1, l, mid, x, y, val); 74 if (y > mid) updateadd(now << 1 | 1, mid + 1, r, x, y, val); 75 pushup(now); 76 } 77 void updatemul(int now, int l, int r, int x, int y, ll val) { 78 if (x <= l && r <= y) { 79 sum[now] *= val; 80 addtag[now] *= val; 81 addmul[now] *= val; 82 return ; 83 } 84 int mid = l + r >> 1; 85 pushdown(now, mid - l + 1, r - mid); 86 if (x <= mid) updatemul(now << 1, l, mid, x, y, val); 87 if (y > mid) updatemul(now << 1 | 1, mid + 1, r, x, y, val); 88 pushup(now); 89 } 90 ll query(int now, int l, int r, int x, int y) { 91 if (x <= l && r <= y) return sum[now]; 92 int mid = l + r >> 1; 93 pushdown(now, mid - l + 1, r - mid); 94 ll ret = 0; 95 if (x <= mid) ret += query(now << 1, l, mid, x, y); 96 if (y > mid) ret += query(now << 1 | 1, mid + 1, r, x, y); 97 return ret; 98 } 99 void updateadd(int from, int to, ll val) { 100 while (top[from] != top[to]) { 101 if (dep[top[from]] < dep[top[to]]) swap(from, to); 102 updateadd(1, 1, n, dfn[top[from]], dfn[from], val); 103 from = fa[top[from]]; 104 } 105 if (dep[from] > dep[to]) swap(from, to); 106 updateadd(1, 1, n, dfn[from], dfn[to], val); 107 } 108 void updatemul(int from, int to, ll val) { 109 while (top[from] != top[to]) { 110 if (dep[top[from]] < dep[top[to]]) swap(from, to); 111 updatemul(1, 1, n, dfn[top[from]], dfn[from], val); 112 from = fa[top[from]]; 113 } 114 if (dep[from] > dep[to]) swap(from, to); 115 updatemul(1, 1, n, dfn[from], dfn[to], val); 116 } 117 ll query(int from, int to) { 118 ll ret = 0; 119 while (top[from] != top[to]) { 120 if (dep[top[from]] < dep[top[to]]) swap(from, to); 121 ret += query(1, 1, n, dfn[top[from]], dfn[from]); 122 from = fa[top[from]]; 123 } 124 if (dep[from] > dep[to]) swap(from, to); 125 ret += query(1, 1, n, dfn[from], dfn[to]); 126 return ret; 127 } 128 ll SHLAK = 18446744073709551615; 129 int main() { 130 while (~scanf("%d", &n)) { 131 cnt = 0; num = 0; 132 memset(head, 0, sizeof(head)); 133 memset(son, 0, sizeof(son)); 134 for (register int i = 2; i <= n; ++i) { 135 int x; scanf("%d", &x); 136 add(x, i); add(i, x); 137 } 138 dfs1(1, 0, 0); 139 dfs2(1, 1); 140 build(1, 1, n); 141 int m; 142 scanf("%d", &m); 143 for (register int i = 1; i <= m; ++i) { 144 int op, x, y; 145 ll z; 146 scanf("%d%d%d", &op, &x, &y); 147 if (op == 1) { 148 scanf("%llu", &z); 149 updatemul(x, y, z); 150 } 151 else if (op == 2) { 152 scanf("%llu", &z); 153 updateadd(x, y, z); 154 } 155 else if (op == 3) { 156 updatemul(x, y, -1); 157 updateadd(x, y, SHLAK); 158 } 159 else { 160 printf("%llu ", query(x, y)); 161 } 162 } 163 } 164 return 0; 165 }