洛谷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;
}
View Code

 

posted @ 2019-07-31 14:05  wangyuchen  阅读(138)  评论(0编辑  收藏  举报