2012中国国家集训队命题答辩tree(伍一鸣)

来源:互联网 发布:如何设计一个软件 编辑:程序博客网 时间:2024/06/12 13:44

Description:

   一棵 n 个点的树,每个点的初始权值为 1。对于这棵树有 q 个操作,每个操作为以下四种操作之一:
   +  u  v  c:uv 的路径上的点的权值都加上自然数 c
     u1  v1  u2  v2: 将树中原有的边 (u1,v1) 删除,加入一条新边 (u2,v2) ,保证操作完之后仍然是一棵树;
     u  v  c:uv 的路径上的点的权值都乘上自然数 c
   /  u  v: 询问 uv 的路径上的点的权值和,求出答案对于 51061 的余数。

   
   
   

Solution:

    LCT 直接上,Splay维护每一条链的和,然后记录一个 add,mult来作为标记。
   
   
   

Code:

#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>#include <iostream>using namespace std;int N,Q;const long long Mod=51061;struct tree_{    int fa1;    int fa2;    int son[2];    long long sum;    long long add;    long long mult;    int rev;    long long Size;}tree[100010]={{0,0,{0},0,0,0,0,0}};struct bian_{    int to;    int next;}bian[200010]={{0,0}};int First[100010]={0};void Add(int p,int q,int k){    bian[k].to=q;    bian[k].next=First[p];    First[p]=k;    return;}void dfs(int cnt,int fa){    tree[cnt].sum=tree[cnt].Size=1;    for(int i=First[cnt];i!=0;i=bian[i].next)    {        if(bian[i].to==fa) continue;        tree[bian[i].to].fa2=cnt;        dfs(bian[i].to,cnt);    }    return;}void rotate(int k){    int Fa=tree[k].fa1;    if(tree[Fa].fa1==0)        swap(tree[Fa].fa2,tree[k].fa2);    int g=(tree[Fa].son[1]==k);    swap(tree[k].Size,tree[Fa].Size);    tree[Fa].Size+=tree[tree[Fa].son[g^1]].Size-tree[tree[k].son[g]].Size;    int SS=tree[Fa].sum;    tree[Fa].sum-=tree[k].sum-tree[tree[k].son[g^1]].sum;    tree[Fa].sum=(tree[Fa].sum+Mod)%Mod;    tree[k].sum=SS;    tree[Fa].son[g]=tree[k].son[g^1];    if(tree[k].son[g^1]!=0)        tree[tree[k].son[g^1]].fa1=Fa;    tree[k].son[g^1]=Fa;    tree[k].fa1=tree[Fa].fa1;    if(tree[Fa].fa1!=0)    {        int gg=(tree[tree[Fa].fa1].son[1]==Fa);        tree[tree[Fa].fa1].son[gg]=k;    }    tree[Fa].fa1=k;    return;}void update(int k){    if(tree[k].fa1!=0)        update(tree[k].fa1);    for(int i=0;i<=1;i++)    {        if(tree[k].son[i]!=0)        {            int child=tree[k].son[i];            tree[child].rev^=tree[k].rev;            tree[child].sum=(tree[child].sum*(tree[k].mult+1)+tree[k].add*tree[child].Size)%Mod;            tree[child].add=(tree[child].add*(tree[k].mult+1)+tree[k].add)%Mod;            tree[child].mult=((tree[child].mult+1)*(tree[k].mult+1)-1)%Mod;            if(tree[k].rev&1)                swap(tree[child].son[0],tree[child].son[1]);        }    }    tree[k].rev=tree[k].add=tree[k].mult=0;    return;}void Splay(int k){    update(k);    for(;tree[k].fa1!=0;)    {        int Fa=tree[k].fa1;        if(tree[Fa].fa1==0)            rotate(k);        else        {            int g1=(tree[Fa].son[1]==k),g2=(tree[tree[Fa].fa1].son[1]==Fa);            if(g1==g2)                rotate(Fa),rotate(k);            else rotate(k),rotate(k);        }    }    return;}void cut(int k,int g){    int child=tree[k].son[g];    swap(tree[child].fa1,tree[child].fa2);    tree[k].sum=(tree[k].sum-tree[child].sum+Mod)%Mod;    tree[k].Size-=tree[child].Size;    tree[k].son[g]=0;    return;}void access(int k){    Splay(k);    if(tree[k].son[1]!=0)        cut(k,1);    for(;;)    {           if(tree[k].fa2==0)            break;        int O=tree[k].fa2;        Splay(O);        if(tree[O].son[1]!=0)            cut(O,1);        tree[O].Size+=tree[k].Size;        tree[O].sum=(tree[O].sum+tree[k].sum)%Mod;        tree[O].son[1]=k;        swap(tree[k].fa1,tree[k].fa2);        Splay(k);    }    return;}int main(){    scanf("%d%d",&N,&Q);    for(int i=1;i<N;i++)    {        int p,q;        scanf("%d%d",&p,&q);        Add(p,q,(i<<1)-1);        Add(q,p,i<<1);    }    dfs(1,0);    for(int i=1;i<=Q;i++)    {        char ch='\0';        for(ch=getchar();!(ch=='-' || ch=='+' || ch=='*' || ch=='/');ch=getchar());        if(ch=='+')        {            int u,v,r;            scanf("%d%d%d",&u,&v,&r);            long long increase=(long long)r%Mod;            access(u);            tree[u].rev^=1;            swap(tree[u].son[0],tree[u].son[1]);            access(v);            update(v);            tree[v].sum=(tree[v].sum+increase*tree[v].Size)%Mod;            tree[v].add=increase;        }        if(ch=='-')        {            int u,v,p,q;            scanf("%d%d%d%d",&u,&v,&p,&q);            access(u);            tree[u].rev^=1;            swap(tree[u].son[0],tree[u].son[1]);            access(v);            tree[v].sum=(tree[v].sum-tree[u].sum+Mod)%Mod;            tree[v].Size-=tree[u].Size;            tree[u].fa1=tree[v].son[0]=0;            access(q);            tree[q].rev^=1;            swap(tree[q].son[0],tree[q].son[1]);            tree[q].fa2=p;        }        if(ch=='*')        {            int u,v,r;            scanf("%d%d%d",&u,&v,&r);            long long cheng=(long long)r%Mod;            access(u);            tree[u].rev^=1;            swap(tree[u].son[0],tree[u].son[1]);            access(v);            update(v);            tree[v].sum=tree[v].sum*cheng%Mod;            tree[v].mult=cheng-1;        }        if(ch=='/')        {            int u,v;            scanf("%d%d",&u,&v);            access(u);            tree[u].rev^=1;            swap(tree[u].son[0],tree[u].son[1]);            access(v);            printf("%d\n",(int)tree[v].sum);        }    }    return 0;}
0 0
原创粉丝点击