社区讨论

LCT求调

P1501[国家集训队] Tree II参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@lugvuh99
此快照首次捕获于
2024/04/01 19:44
2 年前
此快照最后确认于
2024/04/01 19:57
2 年前
查看原帖
CPP
#include<bits/stdc++.h>
using namespace std;
long long n,q;
#define MAXN 500505
long long ch[MAXN][2],Multi[MAXN],s[MAXN],lz[MAXN],v[MAXN];//M:Multilazytag,S=Sum,LZ:sumlazy
bool rev[MAXN];
long long siz[MAXN],f[MAXN];
#define MOD 51061
#define ls(x) (ch[x][0])
#define rs(x) (ch[x][1])


namespace LCT{
    bool isroot(long long x){
        return ls(f[x])==x||rs(f[x])==x;
    }
    bool Get(long long x){return x==rs(f[x]);}
    void pushrev(long long x){swap(ls(x),rs(x));rev[x]^=1;}
    void pushup(long long x){s[x]=(s[ls(x)]+s[rs(x)]+v[x])%MOD;siz[x]=siz[ls(x)]+siz[rs(x)]+1;}
    void push_Multi(long long x,long long c){
        s[x]=(s[x]*c)%MOD;v[x]=(v[x]*c)%MOD;Multi[x]=(Multi[x]*c)%MOD;lz[x]=(lz[x]*c)%MOD;
    }
    void push_Add(long long x,long long c){
        s[x]=(s[x]+c*siz[x])%MOD;v[x]=(v[x]+c)%MOD;lz[x]=(lz[x]+c)%MOD;
    }
    void pushdown(long long x){
        if(Multi[x]!=1)push_Multi(ls(x),Multi[x]),push_Multi(rs(x),Multi[x]),Multi[x]=1;
        if(lz[x]!=0)push_Add(ls(x),lz[x]),push_Add(rs(x),lz[x]),lz[x]=0;
        if(rev[x]){if(ls(x))pushrev(ls(x));if(rs(x))pushrev(rs(x));rev[x]=0;}
    }
    void rotate(long long x){
        long long y=f[x],z=f[y],k=Get(x),w=ch[x][!k];
        if(isroot(y))ch[z][rs(z)==y]=x;
        ch[x][!k]=y;ch[y][k]=w;
        if(w)f[w]=y;
        f[y]=x,f[x]=z;
        pushup(y);
    }
    void Update(long long x){if(isroot(x))Update(f[x]);pushdown(x);}//爬到树根去往下传
    void splay(long long x){
        Update(x);
        while(isroot(x)){
            long long y=f[x],z=f[y];
            if(isroot(y))rotate((((ls(y)==x)^(ls(z)==y))?x:y));
            rotate(x);
        }
        pushup(x);
    }
    void access(long long x){
        for(long long y=0;x;x=f[y=x]){splay(x);rs(x)=y;pushup(x);}
    }
    void makeroot(long long x){access(x);splay(x);pushrev(x);}
    long long findroot(long long x){
        access(x);splay(x);
        while (ls(x)){pushdown(x);x=ls(x);}
        splay(x);
        return x;
    }
    void split(long long x,long long y){makeroot(x);access(y);splay(y);}
    void link(long long x,long long y){makeroot(x);if(findroot(y)!=x)f[x]=y;}
    void cut(long long x,long long y){
        makeroot(x);access(y);splay(y);ls(x)=f[x]=0;
    }
}


int main(){
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    scanf("%lld%lld",&n,&q);
    for(long long i=1;i<=n;++i)v[i]=siz[i]=Multi[i]=1;
    for(long long i=1;i<n;++i ){long long u,v;scanf("%lld%lld",&u,&v);LCT::link(u,v);}
    while(q--){
        string S;cin>>S;
        if(S=="+"){long long u,v,c;scanf("%lld%lld%lld",&u,&v,&c);LCT::split(u,v);LCT::push_Add(u,c);}
        else if(S=="-"){long long u,v,U,V;scanf("%lld%lld%lld%lld",&u,&v,&U,&V);LCT::cut(u,v);LCT::link(U,V);}
        else if(S=="*"){long long u,v,c;scanf("%lld%lld%lld",&u,&v,&c);LCT::split(u,v);LCT::push_Multi(u,c);}
        else {long long u,v;scanf("%lld%lld",&u,&v);LCT::split(u,v);printf("%lld\n",s[u]);
        }
        
    }
    return 0;
}

回复

0 条回复,欢迎继续交流。

正在加载回复...