洛谷 P1501 [国家集训队]Tree II
#include<cstdio> #define Rint register int using namespace std; typedef long long LL; const int N = 100003, mod = 51061; int sta[N], top; namespace LCT { void swap(int &a, int &b){a ^= b ^= a ^= b;} struct Node { int v, fa, siz, ch[2], sum, add, mul; bool rev; } e[N]; void pushup(int x){ e[x].sum = (e[e[x].ch[0]].sum + e[e[x].ch[1]].sum + e[x].v) % mod; e[x].siz = e[e[x].ch[0]].siz + e[e[x].ch[1]].siz + 1; } void pushrev(int x){ e[x].rev ^= 1; swap(e[x].ch[0], e[x].ch[1]); } void pushtag(int x, int add, int mul){ if(!x) return; e[x].sum = ((LL) e[x].sum * mul + (LL) add * e[x].siz) % mod; e[x].add = ((LL) e[x].add * mul + add) % mod; e[x].v = ((LL) e[x].v * mul + add) % mod; e[x].mul = (LL) e[x].mul * mul % mod; } void pushdown(int x){ if(e[x].rev){ e[x].rev = false; if(e[x].ch[0]) pushrev(e[x].ch[0]); if(e[x].ch[1]) pushrev(e[x].ch[1]); } pushtag(e[x].ch[0], e[x].add, e[x].mul); pushtag(e[x].ch[1], e[x].add, e[x].mul); e[x].add = 0; e[x].mul = 1; } bool nroot(int x){ return e[e[x].fa].ch[0] == x || e[e[x].fa].ch[1] == x; } void rotate(int x){ int y = e[x].fa, z = e[y].fa, zson = e[z].ch[1] == y, yson = e[y].ch[1] == x, B = e[x].ch[yson ^ 1]; if(nroot(y)) e[z].ch[zson] = x; e[x].ch[yson ^ 1] = y; e[y].ch[yson] = B; if(B) e[B].fa = y; e[y].fa = x; e[x].fa = z; pushup(y); } void splay(int x){ int now = x; sta[++ top] = x; while(nroot(now)) sta[++ top] = now = e[now].fa; while(top) pushdown(sta[top --]); while(nroot(x)){ int y = e[x].fa, z = e[y].fa; if(nroot(y)) rotate((e[z].ch[1] == y) ^ (e[y].ch[1] == x) ? x : y); rotate(x); } pushup(x); } void access(int x){ for(Rint y = 0;x;y = x, x = e[x].fa){ splay(x); e[x].ch[1] = y; pushup(x); } } void makeroot(int x){ access(x); splay(x); pushrev(x); } int findroot(int x){ access(x); splay(x); while(e[x].ch[0]) {pushdown(x); x = e[x].ch[0];} return x; } void split(int x, int y){ makeroot(x); access(y); splay(y); } void link(int x, int y){ makeroot(x); e[x].fa = y; } void cut(int x, int y){ makeroot(x); if(findroot(y) == x && e[x].fa == y && !e[x].ch[1]){ e[x].fa = e[y].ch[0] = 0; pushup(y); } } } using namespace LCT; int n, q; int main(){ scanf("%d%d", &n, &q); for(Rint i = 1;i <= n;i ++) e[i].v = e[i].sum = e[i].mul = 1; for(Rint i = 1;i < n;i ++){ int a, b; scanf("%d%d", &a, &b); link(a, b); } while(q --){ char opt[5]; scanf("%s", opt); int a, b, c, d; switch(opt[0]){ case '+': scanf("%d%d%d", &a, &b, &c); split(a, b); pushtag(b, c, 1); break; case '-': scanf("%d%d%d%d", &a, &b, &c, &d); cut(a, b); link(c, d); break; case '*': scanf("%d%d%d", &a, &b, &c); split(a, b); pushtag(b, 0, c); break; case '/': scanf("%d%d", &a, &b); split(a, b); printf("%d\n", e[b].sum); } } }