这道题教会了我如何把一道数据结构变难,先是链,然后树,然后动态的树(' '      ) 对于此题的合并不清楚的可以先去做bzoj  2752,但是因为从线段树变成了splay,所以当节点update的时候要考虑自身的影响,对update进行分类讨论。注意翻转标记的时候有些值也会翻转。然后里面有一个细节是询问两个点是否有直接边相连,做法是将一个点a提根,然后一个点b access到根,看a在splay中是不是b的前驱

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 typedef long long ll;
  8 const ll maxn = 51000;
  9 
 10 ll n, m, a[maxn];
 11 
 12 struct node {
 13     ll data, ans, lm, rm, sum, lr, ld, size, p, key;
 14     node *son[2], *fa;
 15 }tr[maxn];
 16 
 17 void test(node* x) {
 18     if(x) {
 19         cout << x-> key <<" "<<x-> size <<" "<< x-> p <<" "<< x-> lr<< endl;
 20         //cout << x-> key <<" "<<x-> data <<" "<< x-> size <<" " << x-> ans <<" "<< x-> sum <<" "<< x-> lm <<" "<< x-> rm << endl; 
 21             for(ll i = 0; i < 2; ++ i) test(x-> son[i]);
 22     }
 23 }
 24 
 25 void update(node* x) {
 26     if(!x-> son[0] && !x-> son[1]) {
 27         x-> ans = x-> lm = x-> rm = x-> sum = x->data; x-> size = 1;
 28     }
 29     else if(x-> son[0] && !x-> son[1]) {
 30         x-> size = x-> son[0]-> size + 1; x-> sum = x-> data + x-> son[0]-> sum;
 31         x-> ans = x-> data * x-> size  + x-> son[0]-> ans + x-> son[0]-> rm;
 32         x-> lm = x-> son[0]-> lm + x-> sum;
 33         x-> rm = x-> son[0]-> rm  + x-> data * x-> size;
 34     }
 35     else if(!x-> son[0] && x-> son[1]) {
 36         x-> size = x-> son[1]-> size + 1; x-> sum = x-> data + x-> son[1]-> sum;
 37         x-> ans = x-> data * x-> size + x-> son[1]-> ans + x-> son[1]-> lm;
 38         x-> lm = x-> data * x-> size + x-> son[1]-> lm;
 39         x-> rm = x-> son[1]-> rm + x-> sum;
 40     }
 41     else {
 42         x-> size = x-> son[0]-> size + x-> son[1]-> size + 1; x-> sum = x-> data + x-> son[1]-> sum + x-> son[0]-> sum;
 43         x-> ans = x-> data * (x-> size + x-> son[0]-> size * x-> son[1]-> size) + x-> son[0]-> ans + x-> son[1]-> ans + x-> son[1]-> lm * (1 + x-> son[0]-> size) + x-> son[0]-> rm * (1 + x-> son[1]-> size);
 44         x-> lm = x-> son[0]-> lm + x-> son[0]-> sum * (x-> son[1]-> size + 1) + x-> data * (x-> son[1]-> size + 1) + x-> son[1]-> lm;
 45         x-> rm = x-> son[1]-> rm + x-> son[1]-> sum * (x-> son[0]-> size + 1) + x-> data * (x-> son[0]-> size + 1) + x-> son[0]-> rm;
 46     }
 47 }
 48 
 49 void swap(node *&a, node *&b) {
 50     node *t = a; a = b, b = t;
 51 } 
 52 
 53 void swap(int &a, int &b) {
 54     int t = a; a = b; b = t;
 55 }
 56 
 57 void pushdown(node* x) {
 58     if(!x) return;
 59     if(x-> lr) {
 60         swap(x-> son[0], x-> son[1]);
 61         for(ll i = 0; i < 2; ++ i) if(x-> son[i]) x-> son[i]-> lr ^= 1, swap(x-> son[i]-> lm, x-> son[i]-> rm);
 62         x-> lr = 0;
 63     }
 64     if(x-> ld) {
 65         for(ll i = 0; i < 2; ++ i) {
 66             if(x-> son[i]) {
 67                 x-> son[i]-> ans += x-> ld * (x-> son[i]-> size * (x-> son[i]-> size + 1) / 2) * (x-> son[i]-> size + 2) / 3;
 68                 x-> son[i]-> sum += x-> ld * x-> son[i]-> size;
 69                 x-> son[i]-> lm += x-> ld * (x-> son[i]-> size * (x-> son[i]-> size + 1) / 2);
 70                 x-> son[i]-> rm += x-> ld * (x-> son[i]-> size * (x-> son[i]-> size + 1) / 2);
 71                 x-> son[i]-> data += x-> ld; x-> son[i]-> ld += x-> ld;
 72             }
 73         }
 74         x-> ld = 0;
 75     }
 76 }
 77 
 78 void rotate(node* x, ll f) {
 79     node* t = x-> fa;
 80     if(t-> fa) {
 81         if(t-> fa-> son[0] == t) t-> fa-> son[0] = x;
 82         else t-> fa-> son[1] = x;
 83     }
 84     //x-> fa = t-> fa, x-> p = t-> p, t-> fa = x;
 85     x-> fa = t-> fa, x-> p = t-> p, x-> ans = t-> ans, x-> lm = t-> lm, x-> rm = t-> rm, x-> size = t-> size, t-> fa = x, x-> sum = t-> sum;
 86     t-> son[f] = x-> son[!f];
 87     if(x-> son[!f]) x-> son[!f]-> fa = t;
 88     x-> son[!f] = t;
 89     update(t); update(x);
 90 }
 91 
 92 void splay(node* x, node *f) {
 93     pushdown(x); 
 94     while(x-> fa != f) {
 95         pushdown(x-> fa-> fa), pushdown(x-> fa), pushdown(x);
 96         if(x-> fa-> fa == f) {
 97             ll a = x-> fa-> son[0] == x ? 0 : 1;
 98             rotate(x, a);
 99         }
100         else {
101             node* t = x-> fa, *r = t-> fa;
102             ll a = r-> son[0] == t ? 0 : 1;
103             ll b = t-> son[0] == x ? 0 : 1;
104             if(a == b) rotate(t, a), rotate(x, b);
105             else rotate(x, b), rotate(x, a);
106         }
107     }
108 }
109 
110 void access(ll cur) {
111     node* x = tr + cur; node* t; ll pp;
112     splay(x, NULL); 
113     if(x-> son[1]) x-> son[1]-> p = cur, x-> son[1]-> fa = NULL, x-> son[1] = NULL, update(x);
114     while((pp = x-> p)) {
115         t = tr + pp; splay(t, NULL);
116         if(t-> son[1]) t-> son[1]-> p = pp, t-> son[1]-> fa = NULL, t-> son[1] = NULL, update(t); 
117         t-> son[1] = x; x-> fa = t; update(t);
118         splay(x, NULL);
119     }
120 }
121 
122 void reserve(ll x) {
123     access(x); (tr + x)-> lr ^= 1; swap((tr + x)-> lm, (tr + x)-> rm);
124 }
125 
126 bool query(ll a, ll b) {
127     reserve(a);
128     access(b);
129     node* t = tr + a;
130     while(t-> fa) t = t-> fa;
131     return (t == (tr + b));
132 }
133 
134 void cut(ll a, ll b) {
135     reserve(a);
136     access(b);
137     node* t = (tr + b)-> son[0];
138     if(!t) return;
139     while(t-> son[1]) t = t-> son[1];
140     if(t == (tr + a)) 
141         (tr + a)-> p = 0, (tr + a)-> fa = NULL, (tr + b)-> son[0] = NULL, update(tr + b);
142 }
143 
144 void link(ll a, ll b) {
145     if(query(a, b) == 0) {
146         (tr + a)-> p = b; 
147     }
148 }
149 
150 ll int_get() {
151     ll x = 0; char c = (char)getchar(); bool f = 0;
152     while(!isdigit(c) && c != '-') c = (char)getchar();
153     if(c == '-') c = (char)getchar(), f = 1;
154     while(isdigit(c)) {
155         x = x * 10 + (int)(c - '0');
156         c = (char)getchar();
157     }
158     return x;
159 }
160 
161 struct edge {
162     ll t; edge* next;
163 }e[maxn * 2], *head[maxn]; ll ne = 0;
164 
165 void addedge(ll f, ll t) {
166     e[ne].t = t, e[ne].next = head[f], head[f] = e + ne ++;
167 }
168 
169 void dfs(ll x, ll fa) {
170     (tr + x)-> p = fa, (tr + x)-> data = (tr + x)-> ans = (tr + x)-> lm = (tr + x)-> rm = a[x], (tr + x)-> size = 1, (tr + x)-> key = x, (tr + x)-> sum = a[x];
171     for(edge* p = head[x]; p; p = p-> next) if(p-> t != fa) dfs(p-> t, x);
172 }
173 
174 void read() {
175     n = int_get(), m = int_get(); 
176     for(ll i = 1; i <= n; ++ i) a[i] = int_get();
177     for(ll i = 1; i < n; ++ i) {
178         ll u = int_get(), v = int_get(); 
179         addedge(u, v), addedge(v, u);
180     }
181     dfs(1, 0);
182 }
183 
184 ll gcd(ll a, ll b) {
185     return a % b == 0 ? b : gcd(b, a % b);
186 }
187 
188 void sov() {
189     for(int i = 1; i <= m; ++ i) {
190         ll opt = int_get(); 
191         if(opt == 1) {
192             ll a, b; a = int_get(), b = int_get(); cut(a, b);
193         }
194         if(opt == 2) {
195             ll a, b; a = int_get(), b = int_get(); link(a, b);
196         }
197         if(opt == 3) {
198             ll a, b; a = int_get(), b = int_get();  ll d = int_get(); 
199             if(query(a, b) == 1) {
200                 node* t = (tr + b); 
201                 t-> data += d;
202                 t-> ans += (t-> size * (t-> size + 1) / 2) * (t-> size + 2) / 3 * d;
203                 t-> lm += (t-> size * (t-> size + 1) / 2) * d;
204                 t-> rm += (t-> size * (t-> size + 1) / 2) * d;
205                 t-> sum += t-> size * d;
206                 t-> ld += d;
207             }
208         }
209         if(opt == 4) {
210             ll a, b; a = int_get(), b = int_get(); 
211             if(query(a, b) == 0) printf("-1\n");
212             else {
213                 //reserve(a), access(b);
214                 ll c = (tr + b)-> ans;
215                 //cout << c << endl;
216                 ll d = (tr + b)-> size * ((tr + b)-> size + 1) / 2;
217                 ll g = gcd(c, d);
218                 printf("%lld/%lld\n", c / g, d / g);
219             }
220             //if(i == 1 || i == 24) cout << i << endl, test(tr + b), cout << endl;
221         }
222     }
223     //for(ll i = 1; i <= n; ++ i) test(tr + i), cout << endl;
224 }
225 
226 int main() {
227     //freopen("test.in", "r", stdin);
228     //freopen("test.out", "w", stdout);
229     read(), sov();  //splay(tr + 2, NULL);
230     //test(tr + 5);
231     return 0;
232 }
View Code