焦作网络赛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)(n1) 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^51n,m,u,v105

1 \le x < 2^{64}1x<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

题目来源

ACM-ICPC 2018 焦作赛区网络预赛

 

题意:

有一棵树 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 }

 

posted @ 2018-09-18 11:25  wyboooo  阅读(201)  评论(0编辑  收藏  举报