[BZOJ 2631]tree
裸LCT。。QAQ写了三遍没写对
真是老了。。QAQ
主要错的地方是
init:
size[i] = sum[i] = val[i] = mul[i] = 1;
pushdown:
注意判断左右儿子是否为空
splay:
前面有pushdown, stack..
while(!isroot(p)){
int x = fa[p], y = fa[x];
if(!isroot(x))...
}
Access:
while(u){
...
c[u][1] = t;
u = fa[u];
}
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define maxn 100010 using namespace std; typedef long long ll; const int md = 51061; int n, q; int c[maxn][2], fa[maxn], val[maxn], mul[maxn], add[maxn]; int sum[maxn], top, st[maxn], size[maxn]; bool rev[maxn]; namespace splay{ inline void Mul(int& x, ll y){ x = x * y % md; } inline void Add(int& x, ll y){ x = (x + y) % md; } void init(){ for(int i = 1; i <= n; i ++) val[i] = mul[i] = 1, add[i] = 0; } inline void pushup(int x){ sum[x] = (sum[c[x][0]] + sum[c[x][1]] + val[x]) % md; size[x] = size[c[x][0]] + size[c[x][1]] + 1; } inline void pushdown(int x){ if(rev[x]){ if(c[x][0])rev[c[x][0]] ^= 1; if(c[x][1])rev[c[x][1]] ^= 1; swap(c[x][0], c[x][1]); rev[x] = 0; } int lc = c[x][0], rc = c[x][1]; if(lc != 0){ if(mul[x] != 1){ Mul(mul[lc], mul[x]); Mul(add[lc], mul[x]); Mul(val[lc], mul[x]); Mul(sum[lc], mul[x]); } if(add[x] != 0){ Add(add[lc], add[x]); Add(val[lc], add[x]); Add(sum[lc], (ll)size[lc] * add[x]); } } if(rc != 0){ if(mul[x] != 1){ Mul(mul[rc], mul[x]); Mul(add[rc], mul[x]); Mul(val[rc], mul[x]); Mul(sum[rc], mul[x]); } if(add[x] != 0){ Add(add[rc], add[x]); Add(val[rc], add[x]); Add(sum[rc], (ll)size[rc] * add[x]); } } mul[x] = 1, add[x] = 0; } inline bool isroot(int x){ return c[fa[x]][0] != x && c[fa[x]][1] != x; } inline void rotate(int p, int x){ int mark = p == c[x][1], y = c[p][mark^1], z = fa[x]; if(c[z][0] == x) c[z][0] = p; if(c[z][1] == x) c[z][1] = p; if(y) fa[y] = x; c[p][mark^1] = x, fa[p] = z; c[x][mark] = y, fa[x] = p; pushup(x); } inline void splay(int p){ st[top = 1] = p; for(int i = p; !isroot(i); i = fa[i]) st[++ top] = fa[i]; while(top) pushdown(st[top --]); while(!isroot(p)){ int x = fa[p], y = fa[x]; if(isroot(x))rotate(p, x); else if(p == c[x][0] ^ x == c[y][0]) rotate(p, x), rotate(p, y); else rotate(x, y), rotate(p, x); } pushup(p); } inline void update(int x, int mu, int ad){ if(mu != 1){ Mul(val[x], mu); Mul(mul[x], mu); Mul(add[x], mu); Mul(sum[x], mu); } if(ad != 0){ Add(val[x], ad); Add(add[x], ad); Add(sum[x], (ll)size[x] * ad); } } } namespace LCT{ void Access(int u){ int t = 0; while(u){ splay::splay(u); c[u][1] = t; t = u; splay::pushup(u); u = fa[u]; } } void Evert(int u){ Access(u); splay::splay(u); rev[u] ^= 1; splay::pushdown(u); } void link(int u, int v){ Evert(u); fa[u] = v; //Access(u); splay::splay(u); } void cut(int u, int v){ Evert(u); Access(v); splay::splay(v); c[v][0] = fa[u] = 0; splay::pushup(v); } void update(int u, int v, int mu, int ad){ Evert(u), Access(v); splay::splay(v); splay::update(v, mu, ad); } int ask(int u, int v){ Evert(u), Access(v); splay::splay(v); return sum[v]; } } int main(){ scanf("%d%d", &n, &q); splay::init(); int u, v, u1, v1, c; for(int i = 1; i < n; i ++){ scanf("%d%d", &u, &v); LCT::link(u, v); } for(int i = 1; i <= q; i ++){ char ch = getchar(); for(; ch < '!'; ch = getchar()); if(ch == '+'){ scanf("%d%d%d", &u, &v, &c); LCT::update(u, v, 1, c); } if(ch == '-'){ scanf("%d%d%d%d", &u, &v, &u1, &v1); LCT::cut(u, v); LCT::link(u1, v1); } if(ch == '*'){ scanf("%d%d%d", &u, &v, &c); LCT::update(u, v, c, 0); } if(ch == '/'){ scanf("%d%d", &u, &v); printf("%d\n", LCT::ask(u, v)); } } return 0; }
给时光以生命,而不是给生命以时光。