焦作网络赛E-JiuYuanWantstoEat【树链剖分】【线段树】
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]a[i], the initial value of a[i]a[i] is 00. The root number of the tree is 11. Now you need to do the following operations:
1)1) Multiply all weight on the path from uu to vv by xx
2)2) For all weight on the path from uu to vv, increasing xx to them
3)3) For all weight on the path from uu to vv, change them to the bitwise NOT of them
4)4) Ask the sum of the weight on the path from uu to vv
The answer modulo 2^{64}264.
Jiu Yuan is a clever girl, but she was not good at algorithm, so she hopes that you can help her solve this problem. Ding\backsim\backsim\backsim∽∽∽
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 00 become 11, and those that are 11 become 00. 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)(n−1) integers b_ibi, which means that the father node of node (i +1)(i+1) is b_ibi.
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)1) If opt is 11, then input 33 integers, u, v, xu,v,x, which means multiply all weight on the path from uu to vv by xx
2)2) If opt is 22, then input 33 integers, u, v, xu,v,x, which means for all weight on the path from uu to vv, increasing xx to them
3)3) If opt is 33, then input 22 integers, u, vu,v, which means for all weight on the path from uu to vv, change them to the bitwise NOT of them
4)4) If opt is 44, then input 22 integers, u, vu,v, and ask the sum of the weights on the path from uu to vv
1 \le n,m,u,v \le 10^51≤n,m,u,v≤105
1 \le x < 2^{64}1≤x<264
Output
For each operation 44, 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路径上所有点值之和
答案取模2^64
思路:
虽然操作乍一看就是线段树 但是和路径相关需要用的树链剖分了
124都是常见操作 只有3比较麻烦
应该要考虑到(-x)%(2^64) = (2^64-1)*x%(2^64)
-x = !x + 1
!x = (2^64-1)*x + (2^64-1) 就可以转换为乘一个数再加一个数了
因此线段树用三个数组维护 一个是sum存区间之和 add是加的lazy数组 mul是乘的lazy数组
由于答案取模2^64 比较特殊
用unsigned long long 位数刚好 溢出相当于取模
由于用到了dfs序 写的时候要注意标号的起始
1 //#include"pch.h" 2 3 #include<iostream> 4 #include<stdio.h> 5 #include<string.h> 6 #include<algorithm> 7 #include<stack> 8 #include<queue> 9 #include<map> 10 #include<vector> 11 #include<cmath> 12 #include<cstring> 13 #include<set> 14 #include<stack> 15 //#include<bits/stdc++.h> 16 17 #define inf 18446744073709551615 18 using namespace std; 19 typedef unsigned long long LL; 20 21 const int MAXN = 2e5 + 5; 22 int siz[MAXN];//number of son 23 int top[MAXN];//top of the heavy link 24 int son[MAXN];//heavy son of the node 25 int dep[MAXN];//depth of the node 26 int faz[MAXN];//father of the node 27 int tid[MAXN];//ID -> DFSID 28 int rnk[MAXN];//DFSID -> ID 29 int head[MAXN], cnt, n, m, cntid; 30 LL sum[MAXN << 2], add[MAXN << 2], mul[MAXN << 2]; 31 struct edge { 32 int to; 33 int next; 34 }edg[MAXN]; 35 36 void addedge(int u, int v) 37 { 38 edg[cnt].to = v; 39 edg[cnt].next = head[u]; 40 head[u] = cnt++; 41 } 42 43 void dfs1(int u, int father, int depth) 44 { 45 dep[u] = depth; 46 faz[u] = father; 47 siz[u] = 1; 48 49 for (int i = head[u]; i != -1; i = edg[i].next) { 50 int v = edg[i].to; 51 if (v != faz[u]) { 52 dfs1(v, u, depth + 1); 53 siz[u] += siz[v]; 54 if (son[u] == -1 || siz[v] > siz[son[u]]) { 55 son[u] = v; 56 } 57 } 58 } 59 } 60 61 void dfs2(int u, int t) 62 { 63 top[u] = t; 64 tid[u] = cntid; 65 rnk[cntid] = u; 66 cntid++; 67 68 if (son[u] == -1) { 69 return; 70 } 71 dfs2(son[u], t); 72 for (int i = head[u]; i != -1; i = edg[i].next) { 73 int v = edg[i].to; 74 if (v != son[u] && v != faz[u]) { 75 dfs2(v, v); 76 } 77 } 78 } 79 80 void pushup(int rt) 81 { 82 sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; 83 } 84 85 void pushdown(int rt, int l, int r) 86 { 87 add[rt << 1] = add[rt << 1] * mul[rt] + add[rt]; 88 add[rt << 1 | 1] = add[rt << 1 | 1] * mul[rt] + add[rt]; 89 mul[rt << 1] = mul[rt << 1] * mul[rt]; 90 mul[rt << 1 | 1] = mul[rt << 1 | 1] * mul[rt]; 91 int m = (l + r) / 2; 92 sum[rt << 1] = sum[rt << 1] * mul[rt] + add[rt] * (m - l + 1); 93 sum[rt << 1 | 1] = sum[rt << 1 | 1] * mul[rt] + add[rt] * (r - m); 94 add[rt] = 0; 95 mul[rt] = 1; 96 } 97 98 void build(int rt, int l, int r) 99 { 100 if (l == r) { 101 return; 102 } 103 int m = (l + r) / 2; 104 build(rt << 1, l, m); 105 build(rt << 1 | 1, m + 1, r); 106 pushup(rt); 107 } 108 109 void update(int L, int R, LL c, int type, int l, int r, int rt) 110 { 111 if (L <= l && R >= r) { 112 if (type == 1) { 113 sum[rt] = sum[rt] * c; 114 add[rt] = add[rt] * c; 115 mul[rt] = mul[rt] * c; 116 } 117 else if (type == 2) { 118 sum[rt] = sum[rt] + (LL)c * (r - l + 1); 119 add[rt] += c; 120 } 121 else if (type == 3) { 122 sum[rt] = sum[rt] * inf + inf * (r - l + 1); 123 add[rt] = add[rt] * inf + inf; 124 mul[rt] *= inf; 125 } 126 return; 127 } 128 pushdown(rt, l, r); 129 int m = (l + r) / 2; 130 if (L <= m) { 131 update(L, R, c, type, l, m, rt << 1); 132 } 133 if (R > m) { 134 update(L, R, c, type, m + 1, r, rt << 1 | 1); 135 } 136 pushup(rt); 137 } 138 139 LL query(int L, int R, int l, int r, int rt) 140 { 141 if (L <= l && R >= r) { 142 return sum[rt]; 143 } 144 int m = (l + r) / 2; 145 LL res = 0; 146 pushdown(rt, l, r); 147 if (L <= m) { 148 res += query(L, R, l, m, rt << 1); 149 } 150 if (R > m) { 151 res += query(L, R, m + 1, r, rt << 1 | 1); 152 } 153 return res; 154 } 155 156 LL query_path(int x, int y) 157 { 158 LL ans = 0; 159 int fx = top[x], fy = top[y]; 160 while (fx != fy) { 161 if (dep[fx] < dep[fy]) { 162 swap(fx, fy); 163 swap(x, y); 164 } 165 ans += query(tid[fx], tid[x], 1, n, 1); 166 x = faz[fx]; 167 fx = top[x]; 168 } 169 170 ans += (dep[x] > dep[y])?query(tid[y], tid[x], 1, n, 1):query(tid[x], tid[y], 1, n, 1); 171 return ans; 172 } 173 174 void update_path(int x, int y, LL c, int type) 175 { 176 int fx = top[x], fy = top[y]; 177 while (fx != fy) { 178 if (dep[fx] < dep[fy]) { 179 swap(fx, fy); 180 swap(x, y); 181 } 182 update(tid[fx], tid[x], c, type, 1, n, 1); 183 x = faz[fx]; 184 fx = top[x]; 185 } 186 if(dep[x] < dep[y]){ 187 swap(x, y); 188 } 189 update(tid[y], tid[x], c, type, 1, n, 1); 190 } 191 192 void init() 193 { 194 memset(head, -1, sizeof(head)); 195 memset(son, -1, sizeof(son)); 196 cnt = 0; 197 cntid = 1; 198 memset(add, 0, sizeof(add)); 199 memset(mul, 1, sizeof(mul)); 200 memset(sum, 0, sizeof(sum)); 201 } 202 203 int main() 204 { 205 while (scanf("%d", &n) != EOF) { 206 init(); 207 for (int i = 1; i < n; i++) { 208 int b; 209 scanf("%d", &b); 210 addedge(b, i + 1); 211 } 212 dfs1(1, 0, 1); 213 dfs2(1, 1); 214 build(1, 1, n); 215 scanf("%d", &m); 216 for (int i = 0; i < m; i++) { 217 int op, u, v; 218 LL x; 219 scanf("%d%d%d", &op, &u, &v); 220 if (op == 1 || op == 2) { 221 scanf("%lld", &x); 222 } 223 if (op == 4) { 224 printf("%llu\n", query_path(u, v)); 225 } 226 else { 227 if(op == 3){ 228 update_path(u, v, 0, op); 229 } 230 else { 231 update_path(u, v, x, op); 232 } 233 } 234 } 235 } 236 return 0; 237 }