这道题教会了我如何把一道数据结构变难,先是链,然后树,然后动态的树(' ' ) 对于此题的合并不清楚的可以先去做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 }