HDU 4010 Query on The Trees(动态树LCT)

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! 

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. 
 
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.

题目大意:给出一棵带点权树,有4种操作:连边x到y;删掉以x为根的树种y与其父节点的连边;把x到y路径上所有点的权值+1;询问x到y路径上的最大点权。

推荐论文:《QTREE解法的一些研究》,参考代码:http://www.cnblogs.com/kuangbin/archive/2013/09/04/3300251.html

代码(1156MS):

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <cstring>
  5 using namespace std;
  6 
  7 const int MAXN = 300010;
  8 const int MAXE = MAXN * 2;
  9 const int INF = 0x7fffffff;
 10 
 11 int ch[MAXN][2], pre[MAXN], key[MAXN];
 12 int add[MAXN], rev[MAXN], maxt[MAXN];
 13 bool rt[MAXN];
 14 
 15 int head[MAXN];
 16 int to[MAXE], next[MAXE];
 17 int ecnt, n, m, op;
 18 
 19 inline void init() {
 20     ecnt = 2;
 21     for(int i = 0; i <= n; ++i) {
 22         head[i] = ch[i][0] = ch[i][1] = 0;
 23         pre[i] = add[i] = rev[i] = 0;
 24         rt[i] = true;
 25     }
 26     maxt[0] = -INF;
 27 }
 28 
 29 inline void add_edge(int u, int v) {
 30     to[ecnt] = v; next[ecnt] = head[u]; head[u] = ecnt++;
 31     to[ecnt] = u; next[ecnt] = head[v]; head[v] = ecnt++;
 32 }
 33 
 34 void dfs(int u) {
 35     for(int p = head[u]; p; p = next[p]) {
 36         int &v = to[p];
 37         if(pre[v]) continue;
 38         pre[v] = u;
 39         dfs(v);
 40     }
 41 }
 42 
 43 inline void update_max(int r) {
 44     maxt[r] = max(max(maxt[ch[r][0]], maxt[ch[r][1]]), key[r]);
 45 }
 46 
 47 inline void update_add(int r, int d) {
 48     if(!r) return ;
 49     key[r] += d;
 50     maxt[r] += d;
 51     add[r] += d;
 52 }
 53 
 54 inline void update_rev(int r) {
 55     if(!r) return ;
 56     swap(ch[r][0], ch[r][1]);
 57     rev[r] ^= 1;
 58 }
 59 
 60 inline void pushdown(int r) {
 61     if(add[r]) {
 62         update_add(ch[r][0], add[r]);
 63         update_add(ch[r][1], add[r]);
 64         add[r] = 0;
 65     }
 66     if(rev[r]) {
 67         update_rev(ch[r][0]);
 68         update_rev(ch[r][1]);
 69         rev[r] = 0;
 70     }
 71 }
 72 
 73 void rotate(int x) {
 74     int y = pre[x], t = ch[y][1] == x;
 75     ch[y][t] = ch[x][!t];
 76     pre[ch[y][t]] = y;
 77     pre[x] = pre[y];
 78     pre[y] = x;
 79     ch[x][!t] = y;
 80     if(rt[y]) rt[y] = false, rt[x] = true;
 81     else ch[pre[x]][ch[pre[x]][1] == y] = x;
 82     update_max(y);
 83 }
 84 
 85 void P(int r) {
 86     if(!rt[r]) P(pre[r]);
 87     pushdown(r);
 88 }
 89 
 90 inline void Splay(int r) {
 91     P(r);
 92     while(!rt[r]) {
 93         int f = pre[r], ff = pre[f];
 94         if(rt[f]) rotate(r);
 95         else if((ch[ff][1] == f) == (ch[f][1] == r)) rotate(f), rotate(r);
 96         else rotate(r), rotate(r);
 97     }
 98     update_max(r);
 99 }
100 
101 inline int access(int x) {
102     int y = 0;
103     while(x) {
104         Splay(x);
105         rt[ch[x][1]] = true, rt[ch[x][1] = y] = false;
106         update_max(x);
107         x = pre[y = x];
108     }
109     return y;
110 }
111 
112 inline void be_root(int r) {
113     access(r);
114     Splay(r);
115     update_rev(r);
116 }
117 
118 inline void lca(int &u, int &v) {
119     access(v), v = 0;
120     while(u) {
121         Splay(u);
122         if(!pre[u]) return ;
123         rt[ch[u][1]] = true;
124         rt[ch[u][1] = v] = false;
125         update_max(u);
126         u = pre[v = u];
127     }
128 }
129 
130 inline int root(int u) {
131     while(pre[u]) u = pre[u];
132     return u;
133 }
134 
135 inline void link(int u, int v) {
136     if(u == v || root(u) == root(v)) puts("-1");
137     else {
138         be_root(u);
139         pre[u] = v;
140     }
141 }
142 
143 inline void cut(int u, int v) {
144     if(u == v || root(u) != root(v)) puts("-1");
145     else {
146         be_root(u);
147         Splay(v);
148         pre[ch[v][0]] = pre[v];
149         pre[v] = 0;
150         rt[ch[v][0]] = true;
151         ch[v][0] = 0;
152         update_max(v);
153     }
154 }
155 
156 inline void modity(int u, int v, int w) {
157     if(root(u) != root(v)) puts("-1");
158     else {
159         lca(u, v);
160         update_add(ch[u][1], w);
161         update_add(v, w);
162         key[u] += w;
163         update_max(u);
164     }
165 }
166 
167 inline void query(int u, int v) {
168     if(root(u) != root(v)) puts("-1");
169     else {
170         lca(u, v);
171         printf("%d
", max(max(maxt[v], maxt[ch[u][1]]), key[u]));
172     }
173 }
174 
175 int main() {
176     while(scanf("%d", &n) != EOF) {
177         init();
178         for(int i = 1; i < n; ++i) {
179             int u, v;
180             scanf("%d%d", &u, &v);
181             add_edge(u, v);
182         }
183         for(int i = 1; i <= n; ++i) scanf("%d", &key[i]);
184         pre[1] = -1; dfs(1); pre[1] = 0;
185         scanf("%d", &m);
186         while(m--) {
187             scanf("%d", &op);
188             if(op == 1) {
189                 int x, y;
190                 scanf("%d%d", &x, &y);
191                 link(x, y);
192             }
193             if(op == 2) {
194                 int x, y;
195                 scanf("%d%d", &x, &y);
196                 cut(x, y);
197             }
198             if(op == 3) {
199                 int x, y, w;
200                 scanf("%d%d%d", &w, &x, &y);
201                 modity(x, y, w);
202             }
203             if(op == 4) {
204                 int x, y;
205                 scanf("%d%d", &x, &y);
206                 query(x, y);
207             }
208         }
209         puts("");
210     }
211 }
View Code