Query on The Trees
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others)
Total Submission(s): 4002 Accepted Submission(s): 1749
Problem Description
We have met so many problems on the tree, so today we will have a query problem on a set of trees.
There are N nodes, each node will have a unique weight Wi. We will have four kinds of operations on it and you should solve them efficiently. Wish you have fun!
There are N nodes, each node will have a unique weight Wi. We will have four kinds of operations on it and you should solve them efficiently. Wish you have fun!
Input
There are multiple test cases in our dataset.
For each case, the first line contains only one integer N.(1 ≤ N ≤ 300000) The next N‐1 lines each contains two integers x, y which means there is an edge between them. It also means we will give you one tree initially.
The next line will contains N integers which means the weight Wi of each node. (0 ≤ Wi ≤ 3000)
The next line will contains an integer Q. (1 ≤ Q ≤ 300000) The next Q lines will start with an integer 1, 2, 3 or 4 means the kind of this operation.
1. Given two integer x, y, you should make a new edge between these two node x and y. So after this operation, two trees will be connected to a new one.
2. Given two integer x, y, you should find the tree in the tree set who contain node x, and you should make the node x be the root of this tree, and then you should cut the edge between node y and its parent. So after this operation, a tree will be separate into two parts.
3. Given three integer w, x, y, for the x, y and all nodes between the path from x to y, you should increase their weight by w.
4. Given two integer x, y, you should check the node weights on the path between x and y, and you should output the maximum weight on it.
For each case, the first line contains only one integer N.(1 ≤ N ≤ 300000) The next N‐1 lines each contains two integers x, y which means there is an edge between them. It also means we will give you one tree initially.
The next line will contains N integers which means the weight Wi of each node. (0 ≤ Wi ≤ 3000)
The next line will contains an integer Q. (1 ≤ Q ≤ 300000) The next Q lines will start with an integer 1, 2, 3 or 4 means the kind of this operation.
1. Given two integer x, y, you should make a new edge between these two node x and y. So after this operation, two trees will be connected to a new one.
2. Given two integer x, y, you should find the tree in the tree set who contain node x, and you should make the node x be the root of this tree, and then you should cut the edge between node y and its parent. So after this operation, a tree will be separate into two parts.
3. Given three integer w, x, y, for the x, y and all nodes between the path from x to y, you should increase their weight by w.
4. Given two integer x, y, you should check the node weights on the path between x and y, and you should output the maximum weight on it.
Output
For each query you should output the correct answer of it. If you find this query is an illegal operation, you should output ‐1.
You should output a blank line after each test case.
You should output a blank line after each test case.
Sample Input
5
1 2
2 4
2 5
1 3
1 2 3 4 5
6
4 2 3
2 1 2
4 2 3
1 3 5
3 2 1 4
4 1 4
Sample Output
3
-1
7
Hint
We define the illegal situation of different operations:
In first operation: if node x and y belong to a same tree, we think it's illegal.
In second operation: if x = y or x and y not belong to a same tree, we think it's illegal.
In third operation: if x and y not belong to a same tree, we think it's illegal.
In fourth operation: if x and y not belong to a same tree, we think it's illegal.1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 using namespace std; 6 const int MAXN=300010; 7 int fir[MAXN],nxt[MAXN<<1],to[MAXN<<1],cnt; 8 int Max[MAXN],fa[MAXN],ch[MAXN][2],flip[MAXN],add[MAXN],key[MAXN]; 9 bool rt[MAXN]; 10 11 void Push_up(int p) 12 { 13 Max[p]=max(key[p],max(Max[ch[p][0]],Max[ch[p][1]])); 14 } 15 16 void Add(int p,int d) 17 { 18 if(!p)return; 19 key[p]+=d; 20 Max[p]+=d; 21 add[p]+=d; 22 } 23 void Flip(int p) 24 { 25 if(!p)return; 26 swap(ch[p][0],ch[p][1]); 27 flip[p]^=1; 28 } 29 void Push_down(int p) 30 { 31 if(add[p]){ 32 Add(ch[p][0],add[p]); 33 Add(ch[p][1],add[p]); 34 add[p]=0; 35 } 36 if(flip[p]){ 37 Flip(ch[p][0]); 38 Flip(ch[p][1]); 39 flip[p]=0; 40 } 41 } 42 43 void Rotate(int x) 44 { 45 int y=fa[x],g=fa[y],c=ch[y][1]==x; 46 ch[y][c]=ch[x][c^1];fa[ch[y][c]]=y; 47 ch[x][c^1]=y;fa[y]=x;fa[x]=g; 48 if(rt[y]) 49 rt[y]=false,rt[x]=true; 50 else 51 ch[g][ch[g][1]==y]=x; 52 Push_up(y); 53 } 54 55 void P(int p) 56 { 57 if(!rt[p])P(fa[p]); 58 Push_down(p); 59 } 60 61 void Splay(int x) 62 { 63 P(x); 64 for(int y=fa[x];!rt[x];Rotate(x),y=fa[x]) 65 if(!rt[y]) 66 Rotate((ch[fa[y]][1]==y)==(ch[y][1]==x)?y:x); 67 Push_up(x); 68 } 69 70 bool Judge(int x,int y) 71 { 72 while(fa[x])x=fa[x]; 73 while(fa[y])y=fa[y]; 74 return x==y; 75 } 76 77 void Access(int x) 78 { 79 int y=0; 80 while(x) 81 { 82 Splay(x); 83 rt[ch[x][1]]=true; 84 rt[ch[x][1]=y]=false; 85 Push_up(x); 86 x=fa[y=x]; 87 } 88 } 89 void Lca(int &x,int &y) 90 { 91 Access(y);y=0; 92 while(true) 93 { 94 Splay(x); 95 if(!fa[x])return; 96 rt[ch[x][1]]=true; 97 rt[ch[x][1]=y]=false; 98 Push_up(x); 99 x=fa[y=x]; 100 } 101 } 102 void Make_root(int x) 103 { 104 Access(x); 105 Splay(x); 106 Flip(x); 107 } 108 109 void Link(int x,int y) 110 { 111 if(Judge(x,y)){ 112 printf("-1 "); 113 return; 114 } 115 Make_root(x); 116 Splay(x); 117 fa[x]=y; 118 } 119 120 void Cut(int x,int y) 121 { 122 if(x==y||!Judge(x,y)){ 123 printf("-1 "); 124 return; 125 } 126 Make_root(x); 127 Splay(y); 128 fa[ch[y][0]]=fa[y]; 129 fa[y]=0; 130 rt[ch[y][0]]=true; 131 ch[y][0]=0; 132 Push_up(y); 133 } 134 135 void Change(int x,int y,int d) 136 { 137 if(!Judge(x,y)){ 138 printf("-1 "); 139 return; 140 } 141 Lca(x,y); 142 Add(ch[x][1],d); 143 Add(y,d); 144 key[x]+=d; 145 Push_up(x); 146 } 147 148 void Query(int x,int y) 149 { 150 if(!Judge(x,y)){ 151 printf("-1 "); 152 return; 153 } 154 Lca(x,y); 155 printf("%d ",max(key[x],max(Max[ch[x][1]],Max[y]))); 156 } 157 158 void addedge(int a,int b) 159 { 160 nxt[++cnt]=fir[a];to[cnt]=b;fir[a]=cnt; 161 } 162 163 void DFS(int node,int pre) 164 { 165 for(int i=fir[node];i;i=nxt[i]) 166 if(to[i]!=pre){ 167 fa[to[i]]=node; 168 DFS(to[i],node); 169 } 170 } 171 void Init() 172 { 173 memset(fir,0,sizeof(fir)); 174 memset(ch,0,sizeof(ch)); 175 memset(fa,0,sizeof(fa)); 176 memset(rt,-1,sizeof(rt)); 177 memset(flip,0,sizeof(flip)); 178 memset(add,0,sizeof(add)); 179 cnt=0;Max[0]=-2100000000; 180 } 181 int main() 182 { 183 int Q,n,x,y,d,k; 184 while(~scanf("%d",&n)) 185 { 186 Init(); 187 for(int i=1;i<n;i++){ 188 scanf("%d%d",&x,&y); 189 addedge(x,y); 190 addedge(y,x); 191 } 192 for(int i=1;i<=n;i++){ 193 scanf("%d",&key[i]); 194 Max[i]=key[i]; 195 } 196 DFS(1,1); 197 scanf("%d",&Q); 198 while(Q--) 199 { 200 scanf("%d",&k); 201 if(k==1){ 202 scanf("%d%d",&x,&y); 203 Link(x,y); 204 } 205 else if(k==2){ 206 scanf("%d%d",&x,&y); 207 Cut(x,y); 208 } 209 else if(k==3){ 210 scanf("%d%d%d",&d,&x,&y); 211 Change(x,y,d); 212 } 213 else if(k==4){ 214 scanf("%d%d",&x,&y); 215 Query(x,y); 216 } 217 } 218 printf(" "); 219 } 220 return 0; 221 }