LCT(维护加乘标记)--luogu P1501 [国家集训队]Tree II

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sizeof_you/article/details/84652174

传送门

就是链上维护加和乘的标记,先乘后加
没开long long wa到怀疑人生祭

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 100005
#define ls ch[x][0]
#define rs ch[x][1]
#define fa f[x]
#define LL long long
#define int LL
using namespace std;

inline int rd(){
    int x=0,f=1;char c=' ';
    while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
    while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
    return x*f;
}

int n,q;
int f[N],ch[N][2],rev[N],sum[N],tag1[N],tag2[N],val[N],siz[N];
const int mod=51061;

inline int get(int x){return ch[fa][1]==x;}
inline int isrt(int x){return ch[fa][0]!=x && ch[fa][1]!=x;}
inline void update(int x){sum[x]=(sum[ls]+sum[rs]+val[x])%mod;siz[x]=siz[ls]+siz[rs]+1;}
inline void rever(int x){rev[x]^=1;swap(ls,rs);}
inline void pushdown(int x){
    if(rev[x]){
    	if(ls) rever(ls);
    	if(rs) rever(rs);
    	rev[x]=0;
    }
    if(tag2[x]!=1){
        int t=tag2[x]; tag2[x]=1;
        if(ls){
        	val[ls]=1LL*val[ls]*t%mod; tag1[ls]=1LL*tag1[ls]*t%mod; tag2[ls]=1LL*tag2[ls]*t%mod;
            sum[ls]=1LL*sum[ls]*t%mod;		
        }
        if(rs){
        	val[rs]=1LL*val[rs]*t%mod; tag1[rs]=1LL*tag1[rs]*t%mod; tag2[rs]=1LL*tag2[rs]*t%mod;
            sum[rs]=1LL*sum[rs]*t%mod;
        }
    }
    if(tag1[x]!=0){
        int t=tag1[x]; tag1[x]=0;
        if(ls){
        	(val[ls]+=t)%=mod; (tag1[ls]+=t)%=mod;
        	(sum[ls]+=1LL*t*siz[ls]%mod)%=mod;
        }
        if(rs){
        	(val[rs]+=t)%=mod; (tag1[rs]+=t)%=mod;
        	(sum[rs]+=1LL*t*siz[rs]%mod)%=mod;
        }
    }
//	update(ls); update(rs);
}
void pushup(int x){if(!isrt(x)) pushup(fa);pushdown(x);}

inline void rotate(int x){
    int old=f[x],oldf=f[old],wh=get(x);
    if(!isrt(old)) ch[oldf][get(old)]=x;
    ch[old][wh]=ch[x][wh^1]; f[ch[x][wh^1]]=old;
    ch[x][wh^1]=old; f[x]=oldf; f[old]=x;
    update(old); update(x);
}
inline void splay(int x){
    pushup(x);
    for(;!isrt(x);rotate(x))
        if(!isrt(fa)) rotate(get(x)==get(fa)?fa:x);
}

inline void access(int x){
    for(int y=0;x;y=x,x=fa) splay(x),rs=y,update(x);
}
inline void makeroot(int x){
    access(x); splay(x); rever(x);
}
inline int findroot(int x){
    access(x); splay(x);
    while(ls) pushdown(x),x=ls; return x;
}
inline void split(int x,int y){
    makeroot(x); access(y); splay(y); 
}
inline void link(int x,int y){
    if(findroot(x)==findroot(y)) return;
    makeroot(x); f[x]=y;
}
inline void cut(int x,int y){
    if(findroot(x)!=findroot(y)) return;
    split(x,y);
    if(ch[y][0]==x && !ch[x][1])
    	f[x]=ch[y][0]=0,update(y);
}

char s[10];
int x,y,z,p;

signed main(){
    n=rd(); q=rd();
    for(int i=1;i<=n;i++) val[i]=1,tag2[i]=1;
    for(int i=1;i<n;i++){
        x=rd(),y=rd();
        link(x,y);
    }
    while(q--){
        scanf("%s",s);
        if(s[0]=='+'){
            x=rd(),y=rd(),z=rd();
            split(x,y); (sum[y]+=1LL*siz[y]*z%mod)%=mod;
            (val[y]+=z%mod)%=mod; (tag1[y]+=z)%=mod;
        }
        if(s[0]=='-'){
            x=rd(),y=rd(),z=rd(),p=rd();
            cut(x,y); link(z,p);
        }
        if(s[0]=='*'){
            x=rd(),y=rd(),z=rd();
            split(x,y); 
            val[y]=1LL*val[y]*z%mod; sum[y]=1LL*sum[y]*z%mod;
        	tag1[y]=1LL*tag1[y]*z%mod; tag2[y]=1LL*tag2[y]*z%mod;
        }
        if(s[0]=='/'){
        	x=rd(),y=rd();
        	split(x,y); printf("%lld\n",sum[y]%mod);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sizeof_you/article/details/84652174