bzoj2631: tree

来源:互联网 发布:噪音测量软件 编辑:程序博客网 时间:2024/05/20 23:30

切掉了第四题LCT,表示这题不错,由于两个继承标记的相互**场面一度十分混乱,再加上mod^2>int ,气氛一度十分尴尬。。最后30s跑了28s+令我感到世界还是有爱的gggg自己垃圾还怪题目

#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;}
原创粉丝点击