bzoj2631: tree

来源:互联网 发布:公务员上岸经验知乎 编辑:程序博客网 时间:2024/05/16 07:40

lct;
注意标记可以看作a*x+b

#include<cstdio>#include<algorithm>#define rep(i,k,n) for(int i=k;i<=(n);i++)#define mod 51061#define ls ch[x][0]#define rs ch[x][1]using namespace std;const int N=100005;typedef unsigned int ll;int n,q,ch[N][2],fa[N],size[N],sta[N],top=0;bool rev[N];ll sum[N],cheng[N],jia[N],val[N];bool isroot(int x){    return (ch[fa[x]][0]!=x && ch[fa[x]][1]!=x || !x);}inline void up(int x){    sum[x]=(sum[ls]+val[x]+sum[rs])%mod;    size[x]=(size[ls]+size[rs]+1)%mod;}inline void cal(int x,int m,int a){    if(!x)return;    val[x]=(val[x]*m+a)%mod;    sum[x]=(sum[x]*m+a*size[x])%mod;    jia[x]=(jia[x]*m+a)%mod;    cheng[x]=(cheng[x]*m)%mod;}inline void down(int x){if(!x)return;    if(rev[x]){rev[x]^=1;swap(ls,rs);rev[ls]^=1;rev[rs]^=1;}    if(cheng[x]!=1 || jia[x]!=0){        cal(ls,cheng[x],jia[x]),cal(rs,cheng[x],jia[x]);    }    cheng[x]=1,jia[x]=0;}inline void relax(int x){    sta[++top]=x;for(;!isroot(x);x=fa[x])sta[++top]=fa[x];    while(top)down(sta[top]),top--;}void rotate(int x,int d){    int y=fa[x];    ch[y][d^1]=ch[x][d];    if(ch[x][d])    fa[ch[x][d]]=y;    if(!isroot(y))ch[fa[y]][ch[fa[y]][1]==y]=x;   //////    fa[x]=fa[y];    ch[x][d]=y;    fa[y]=x;    up(y);}void splay(int x){    relax(x);    while(!isroot(x)){        if(isroot(fa[x]))rotate(x,ch[fa[x]][0]==x);        else{int y=fa[x];            int d=ch[fa[y]][0]==y;            if(ch[y][d]==x)rotate(x,d^1),rotate(x,d);            else rotate(y,d),rotate(x,d);        }        up(x);    }}/*void rotate(int x){    int y=fa[x],z=fa[y],l,r;    l=(ch[y][1]==x);r=l^1;    if(!isroot(y))ch[z][ch[z][1]==y]=x;    fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;    ch[y][l]=ch[x][r];ch[x][r]=y;    up(y);up(x);}void splay(int x){    sta[++top]=x;    for(int i=x;!isroot(i);i=fa[i])        sta[++top]=fa[i];    while(top)down(sta[top--]);    while(!isroot(x))    {        int y=fa[x],z=fa[y];        if(!isroot(y))        {            if(ch[y][0]==x^ch[z][0]==y)rotate(x);            else rotate(y);        }        rotate(x);    }}*/int access(int x){int y=0;   for(;x;y=x,x=fa[x]){      splay(x);      ch[x][1]=y;      up(x);   }return y;}void makeroot(int x){    access(x);    splay(x);    rev[x]^=1;}void split(int x,int y){    makeroot(y);    access(x);    splay(x);}inline void link(int x,int y){    makeroot(x);fa[x]=y;}inline void cut(int x,int y){    makeroot(x);access(y);splay(y);ch[y][0]=fa[x]=0;}int main(){//freopen("in.in","r",stdin);    scanf("%d%d",&n,&q);    int x,y,x1,y1,z;    rep(i,1,n)val[i]=sum[i]=size[i]=cheng[i]=1;    rep(i,1,n-1){        scanf("%d%d",&x,&y);        link(x,y);    }    char s[20];    while(q--){        scanf("%s",s);        if(s[0]=='+'){            scanf("%d%d%d",&x,&y,&z);            split(x,y);cal(x,1,z);        }        if(s[0]=='*'){            scanf("%d%d%d",&x,&y,&z);            split(x,y);cal(x,z,0);        }        if(s[0]=='-'){            scanf("%d%d%d%d",&x,&y,&x1,&y1);            cut(x,y);link(x1,y1);        }        if(s[0]=='/'){            scanf("%d%d",&x,&y);            split(x,y);            printf("%d\n",sum[x]);        }    }    return 0;}//主要是标记下传,数分为值与标记,‘*’影响‘*’,‘+',+影响+; 
0 0
原创粉丝点击