洛谷P1501[国家集训队]Tree II(LCT)
LCT板子题。。。维护区间乘、区间加、区间反转(LCT自带)三个标记,维护就可以了。
#include<cstdio> #include<cctype> typedef long long ll; const int mod=51061; const int N=100050; char rB[1<<21],*S,*T,wB[1<<21]; int wp=-1; inline char gc(){return S==T&&(T=(S=rB)+fread(rB,1,1<<21,stdin),S==T)?EOF:*S++;} inline void flush(){fwrite(wB,1,wp+1,stdout);wp=-1;} inline void pc(char c){if(wp+1==(1<<21))flush();wB[++wp]=c;} inline char rdc(){ char c=gc(); while(isspace(c))c=gc(); return c; } inline int rdi(){ char c=gc(); while(!isdigit(c))c=gc(); int x=c&15; for(c=gc();isdigit(c);c=gc())x=(x<<3)+(x<<1)+(c&15); return x; } short buf[15]; inline void wt(int x){ short l=-1; while(x>9){ buf[++l]=x%10; x/=10; } pc(x|48); while(l>=0)pc(buf[l--]|48); pc('\n'); } int f[N],ch[N][2],sz[N],val[N],sum[N],mulv[N],addv[N],st[N],sl=-1; bool tag[N]; inline void Swap(int &a,int &b){int t=a;a=b;b=t;} inline bool isrt(int o){return ch[f[o]][0]!=o&&ch[f[o]][1]!=o;} inline bool dir(int o){return ch[f[o]][1]==o;} inline void cov(int o,int x){if(o){mulv[o]=(ll)mulv[o]*x%mod;addv[o]=(ll)addv[o]*x%mod;sum[o]=(ll)sum[o]*x%mod;val[o]=(ll)val[o]*x%mod;}} inline void plus(int o,int x){if(o){addv[o]=(addv[o]+x)%mod;sum[o]=(sum[o]+(ll)x*sz[o])%mod;val[o]=(val[o]+x)%mod;}} inline void flip(int o){if(o){tag[o]^=1;Swap(ch[o][0],ch[o][1]);}} inline void pushup(int o){sz[o]=1+sz[ch[o][0]]+sz[ch[o][1]];sum[o]=(val[o]+sum[ch[o][0]]+sum[ch[o][1]])%mod;} inline void pushd(int o){ if(mulv[o]!=1){ cov(ch[o][0],mulv[o]);cov(ch[o][1],mulv[o]); mulv[o]=1; } if(addv[o]){ plus(ch[o][0],addv[o]);plus(ch[o][1],addv[o]); addv[o]=0; } if(tag[o]){ flip(ch[o][0]);flip(ch[o][1]); tag[o]=0; } } inline void rot(int o){ int fa=f[o]; bool d=dir(o); f[o]=f[fa]; if(!isrt(fa))ch[f[fa]][dir(fa)]=o; if(ch[fa][d]=ch[o][d^1])f[ch[fa][d]]=fa; f[ch[o][d^1]=fa]=o; pushup(fa);pushup(o); } inline void splay(int o){ int k=st[++sl]=o; while(!isrt(k)){k=f[k];st[++sl]=k;} while(sl>=0)pushd(st[sl--]); for(;!isrt(o);rot(o))if(!isrt(f[o]))rot((dir(o)^(dir(f[o])))?o:f[o]); } inline void access(int x){ for(int y=0;x;x=f[y=x]){ splay(x); ch[x][1]=y; pushup(x); } } inline void makert(int x){ access(x);splay(x); flip(x); } inline void split(int x,int y){ makert(x);access(y);splay(y); } inline void link(int x,int y){ makert(x); f[x]=y; } inline void cut(int x,int y){ makert(x);access(y);splay(x); ch[x][1]=f[y]=0; } int main(){ int n=rdi(),q=rdi(),i,u,v,x,y; char opt; for(i=1;i<=n;++i)val[i]=sum[i]=sz[i]=mulv[i]=1; for(i=1;i<n;++i){ u=rdi();v=rdi(); link(u,v); } while(q--){ opt=rdc();u=rdi();v=rdi(); if(opt=='+'){ split(u,v); plus(v,rdi()); }else if(opt=='-'){ x=rdi();y=rdi(); cut(u,v);link(x,y); }else if(opt=='*'){ split(u,v); cov(v,rdi()); }else if(opt=='/'){ split(u,v); wt(sum[v]); } } flush(); return 0; }