BZOJ 2631: tree 【LCT维护链上加乘运算】

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/C20181220_xiang_m_y/article/details/88673097

板题,维护add,mul,siz,val,sum。
下传的时候优先乘法。
Code:

#include<cstdio>
#include<cctype>
#include<cstring>
#include<map>
#include<algorithm>
#define maxn 100005
using namespace std;
inline void read(int &a){
    char c;while(!isdigit(c=getchar()));
    for(a=c-'0';isdigit(c=getchar());a=a*10+c-'0');
}
inline void print(int a){
    if(a>=10) print(a/10);
    putchar(a%10+48);
}
const int mod = 51061;
namespace LCT{
    int ch[maxn][2],fa[maxn],add[maxn],mul[maxn],sum[maxn],siz[maxn],v[maxn];
    bool rev[maxn];
    #define il inline
    #define lc ch[x][0]
    #define rc ch[x][1]
    inline bool isc(int x){return ch[fa[x]][1]==x;}
    il bool isr(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
    void upd_add(int x,int d){
        if(!x) return;
        sum[x]=(sum[x]+1ll*d*siz[x])%mod;
        add[x]=(add[x]+d)%mod;
        v[x]=(v[x]+d)%mod;
    }
    void upd_mul(int x,int d){
        if(!x) return;
        sum[x]=1ll*sum[x]*d%mod;
        mul[x]=1ll*mul[x]*d%mod;
        add[x]=1ll*add[x]*d%mod;
        v[x]=1ll*v[x]*d%mod;
    }
    il void pd(int x){
        if(rev[x]) swap(lc,rc),rev[x]=0,rev[lc]^=1,rev[rc]^=1;
        if(mul[x]!=1) upd_mul(lc,mul[x]),upd_mul(rc,mul[x]),mul[x]=1;
        if(add[x]) upd_add(lc,add[x]),upd_add(rc,add[x]),add[x]=0;
    }
    il void pdpath(int x){if(!isr(x)) pdpath(fa[x]);pd(x);}
    il void upd(int x){
        sum[x]=(sum[lc]+sum[rc]+v[x])%mod;
        siz[x]=siz[lc]+siz[rc]+1;
    }
    il void rot(int x){
        int y=fa[x],z=fa[y],c=isc(x);
        if(!isr(y)) ch[z][ch[z][1]==y]=x;
        (ch[y][c]=ch[x][!c])&&(fa[ch[y][c]]=y);
        fa[ch[x][!c]=y]=x,fa[x]=z;
        upd(y),upd(x);
    }
    il void splay(int x){
        pdpath(x);
        for(;!isr(x);rot(x))
            if(!isr(fa[x])) rot(isc(fa[x])==isc(x)?fa[x]:x);
    }
    il int access(int x,int y=0){
        for(;x;x=fa[y=x]) splay(x),rc=y,upd(x);
        return y;
    }
    il void bert(int x){
        access(x),splay(x),rev[x]^=1;
    }
    il void link(int x,int y){
        bert(x),fa[x]=y;
    }
    il void cut(int x,int y){
        bert(x),access(y),splay(y);
        fa[x]=ch[y][0]=0;
        upd(y);
    }
    il int split(int x,int y){
        bert(x),access(y),splay(y);
        return y;
    }
    il void modify_add(int x,int y,int d){upd_add(split(x,y),d);}
    il void modify_mul(int x,int y,int d){upd_mul(split(x,y),d);}
    il int qsum(int x,int y){return sum[split(x,y)];}
}
using namespace LCT;
int n,m,x,y,d;
char c;
int main()
{
    read(n),read(m);
    for(int i=1;i<=n;i++) siz[i]=mul[i]=sum[i]=v[i]=1;
    for(int i=1;i<n;i++) read(x),read(y),link(x,y);
    while(m--){
        c=getchar(),read(x),read(y);
        if(c=='+') read(d),modify_add(x,y,d);
        if(c=='*') read(d),modify_mul(x,y,d);
        if(c=='/') print(qsum(x,y)),putchar('\n');
        if(c=='-') cut(x,y),read(x),read(y),link(x,y);
    }
}

猜你喜欢

转载自blog.csdn.net/C20181220_xiang_m_y/article/details/88673097