bzoj2631: tree

 

搬运。要开LL,注意两个遗传标记之间影响。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const int mod=51061;
struct node
{
    int f,c,son[2];
    LL d,s,ad,ch;
    bool fz;
}tr[310000];
void add(int x)
{
    if(x==0)return ;
    tr[x].s=(tr[x].s+tr[x].ad*tr[x].c)%mod;
    tr[x].d=(tr[x].d+tr[x].ad)%mod;
    int lc=tr[x].son[0],rc=tr[x].son[1];
    tr[lc].ad=(tr[lc].ad+tr[x].ad)%mod;
    tr[rc].ad=(tr[rc].ad+tr[x].ad)%mod;
    tr[x].ad=0;
}
void mul(int x)
{
    if(x==0)return ;
    tr[x].s=(tr[x].s*tr[x].ch)%mod;
    tr[x].d=(tr[x].d*tr[x].ch)%mod;
    int lc=tr[x].son[0],rc=tr[x].son[1];
    tr[lc].ch=(tr[lc].ch*tr[x].ch)%mod;
    tr[lc].ad=(tr[lc].ad*tr[x].ch)%mod;
    tr[rc].ch=(tr[rc].ch*tr[x].ch)%mod;
    tr[rc].ad=(tr[rc].ad*tr[x].ch)%mod;
    tr[x].ch=1;
}
void update(int x)
{
    int lc=tr[x].son[0],rc=tr[x].son[1];
    tr[x].c=tr[lc].c+tr[rc].c+1;
    if(tr[lc].ch!=1)mul(lc);
    if(tr[rc].ch!=1)mul(rc);
    if(tr[lc].ad!=0)add(lc);
    if(tr[rc].ad!=0)add(rc);
    tr[x].s=(tr[lc].s+tr[rc].s+tr[x].d)%mod;
}
void reverse(int x)
{
    tr[x].fz=false;
    swap(tr[x].son[0],tr[x].son[1]);
    int lc=tr[x].son[0],rc=tr[x].son[1];
    tr[lc].fz=1-tr[lc].fz;
    tr[rc].fz=1-tr[rc].fz;
}
void rotate(int x,int w)
{
    int f=tr[x].f,ff=tr[f].f;
    int R,r;
     
    R=f;r=tr[x].son[w];
    tr[R].son[1-w]=r;
    if(r!=0)tr[r].f=R;
     
    R=ff;r=x;
         if(tr[R].son[0]==f)tr[R].son[0]=r;
    else if(tr[R].son[1]==f)tr[R].son[1]=r;
    tr[r].f=R;
     
    R=x;r=f;
    tr[R].son[w]=r;
    tr[r].f=R;
     
    update(f);
    update(x);
}
int tmp[310000];
void splay(int x,int rt)
{
    int s=0,i=x;
    while(tr[i].f!=rt&&(tr[tr[i].f].son[0]==i||tr[tr[i].f].son[1]==i))
    {
        tmp[++s]=i;
        i=tr[i].f;
    } 
    tmp[++s]=i;
    while(s!=0)
    {
        i=tmp[s];s--;
        if(tr[i].fz==true)reverse(i);
        if(tr[i].ch!=1)mul(i);
        if(tr[i].ad!=0)add(i);
    }
     
    while(tr[x].f!=rt&&(tr[tr[x].f].son[0]==x||tr[tr[x].f].son[1]==x))
    {
        int f=tr[x].f,ff=tr[f].f;
        if(ff==rt||(tr[ff].son[0]!=f&&tr[ff].son[1]!=f))
        {
            if(x==tr[f].son[0])rotate(x,1);
            else               rotate(x,0);
        }
        else
        {
                 if(tr[f].son[0]==x&&tr[ff].son[0]==f){rotate(f,1);rotate(x,1);}
            else if(tr[f].son[1]==x&&tr[ff].son[0]==f){rotate(x,0);rotate(x,1);}
            else if(tr[f].son[0]==x&&tr[ff].son[1]==f){rotate(x,1);rotate(x,0);}
            else if(tr[f].son[1]==x&&tr[ff].son[1]==f){rotate(f,0);rotate(x,0);}
        }
    }
}
int n;
void make_tree()
{
    tr[0].f=0;tr[0].c=0;
    tr[0].d=0;tr[0].s=0;
    tr[0].son[0]=tr[0].son[1]=0;
    tr[0].ad=0;tr[0].ch=1;
    tr[0].fz=false;
    for(int i=1;i<=n;i++)
    {
        tr[i].f=0;tr[i].c=1;
        tr[i].d=1;tr[i].s=1;
        tr[i].son[0]=tr[i].son[1]=0;
        tr[i].ad=0;tr[i].ch=1;
        tr[i].fz=false;
    }
}
void access(int x) 
{
    int y=0;
    while(x!=0)
    {
        splay(x,0);
        tr[x].son[1]=y;
        if(y!=0)tr[y].f=x;
        y=x;x=tr[x].f;
    }
}
void makeroot(int x)
{
    access(x);splay(x,0);
    tr[x].fz=1-tr[x].fz;
}
void link(int x,int y)
{
    makeroot(x);tr[x].f=y;access(x);
}
void cut(int x,int y)
{
    makeroot(x);
    access(y);splay(y,0);
    tr[tr[y].son[0]].f=0;tr[y].son[0]=0;
    update(y);
}
int find_root(int x)
{
    access(x);splay(x,0);
    while(tr[x].son[0]!=0)x=tr[x].son[0];
    return x;
}
void increase(int x,int y,LL W)
{
    makeroot(x);
    access(y);splay(y,0);
    tr[y].ad=(tr[y].ad+W)%mod;
}
void multiply(int x,int y,LL W)
{
    makeroot(x);
    access(y);splay(y,0);
    tr[y].ch=(tr[y].ch*W)%mod;
}
LL getsum(int x,int y)
{
    makeroot(x);
    access(y);splay(y,0);
    update(y);return tr[y].s%mod;
}
struct edge
{
    int x,y;
}e[310000];
char ss[10];
int main()
{
//  freopen("tree.in","r",stdin);
//  freopen("tree.out","w",stdout);
    int m,x,y;
    LL W;
    scanf("%d%d",&n,&m);
    for(int i=1;i<n;i++)scanf("%d%d",&e[i].x,&e[i].y);
    make_tree();
    for(int i=1;i<n;i++)link(e[i].x,e[i].y);
    for(int i=1;i<=m;i++)
    {
        scanf("%s",ss+1);
        if(ss[1]=='+')
        {
            scanf("%d%d%lld",&x,&y,&W);
            increase(x,y,W);
        }
        else if(ss[1]=='*')
        {
            scanf("%d%d%lld",&x,&y,&W);
            multiply(x,y,W);
        }
        else if(ss[1]=='-')
        {
            scanf("%d%d",&x,&y);cut(x,y);
            scanf("%d%d",&x,&y);link(x,y);
        }
        else
        {
            scanf("%d%d",&x,&y);
            printf("%lld\n",getsum(x,y));
        }
    }
    return 0;
}

 

posted @ 2017-12-28 13:41  AKCqhzdy  阅读(152)  评论(0编辑  收藏  举报