bzoj 2631: tree

来源:互联网 发布:数据圈付费社区 编辑:程序博客网 时间:2024/06/07 12:48

Description

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

Input

  第一行两个整数n,q
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作

Output

  对于每个/对应的答案输出一行

Sample Input

3 2
1 2
2 3
* 1 3 4
/ 1 1

Sample Output

4


HINT

数据规模和约定

10%的数据保证,1<=n,q<=2000

另外15%的数据保证,1<=n,q<=5*10^4,没有-操作,并且初始树为一条链

另外35%的数据保证,1<=n,q<=5*10^4,没有-操作

100%的数据保证,1<=n,q<=10^5,0<=c<=10^4


用LCT维护即可

注意加法和乘法标记合并时候的顺序

用long long存储结果结果TLE了

发现Mod^2<unsigned int

所以用unsigned int存就可以过了

#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<algorithm>using namespace std;int n;unsigned int mod=51061;struct line{     int s,t;}a[100001];struct tree{     int l,r;     int fa;     int rev;     unsigned int sz,val,tag,tagx;     bool rt;}tr[800001];unsigned int val[200001];tree nx;inline void update_rev(int x){     if(x==0)          return ;     int t=tr[x].l;     tr[x].l=tr[x].r;     tr[x].r=t;     tr[x].rev^=1;}inline void push_up(int x){     tr[x].sz=(tr[tr[x].l].sz+tr[tr[x].r].sz+1)%mod;     tr[x].val=(tr[tr[x].l].val+tr[tr[x].r].val+val[x])%mod;}inline void push_down(int x){     if(tr[x].rev)     {          update_rev(tr[x].l);          update_rev(tr[x].r);          tr[x].rev=0;     }     val[tr[x].l]=(val[tr[x].l]*tr[x].tagx)%mod;     val[tr[x].r]=(val[tr[x].r]*tr[x].tagx)%mod;     tr[tr[x].l].val=tr[tr[x].l].val*tr[x].tagx%mod;     tr[tr[x].r].val=tr[tr[x].r].val*tr[x].tagx%mod;     tr[tr[x].l].tag=(tr[tr[x].l].tag*tr[x].tagx)%mod;     tr[tr[x].r].tag=(tr[tr[x].r].tag*tr[x].tagx)%mod;     tr[tr[x].l].tagx=(tr[tr[x].l].tagx*tr[x].tagx)%mod;     tr[tr[x].r].tagx=(tr[tr[x].r].tagx*tr[x].tagx)%mod;     tr[x].tagx=1;     val[tr[x].l]=(val[tr[x].l]+tr[x].tag)%mod;     val[tr[x].r]=(val[tr[x].r]+tr[x].tag)%mod;     tr[tr[x].l].val=(tr[tr[x].l].val+tr[x].tag*tr[tr[x].l].sz%mod)%mod;     tr[tr[x].r].val=(tr[tr[x].r].val+tr[x].tag*tr[tr[x].r].sz%mod)%mod;     tr[tr[x].l].tag=(tr[tr[x].l].tag+tr[x].tag)%mod;     tr[tr[x].r].tag=(tr[tr[x].r].tag+tr[x].tag)%mod;     tr[x].tag=0;}inline void push(int x){     if(!tr[x].rt)          push(tr[x].fa);     push_down(x);}inline void zig(int x){ tr[0]=nx;     int t=tr[x].l;     tr[x].l=tr[t].r;     tr[tr[t].r].fa=x;     tr[t].r=x;     tr[t].fa=tr[x].fa;     tr[x].fa=t;     if(tr[x].rt)     {          tr[x].rt=false;          tr[t].rt=true;     }     else     {          if(x==tr[tr[t].fa].l)               tr[tr[t].fa].l=t;          else               tr[tr[t].fa].r=t;     }     push_up(x);}inline void zag(int x){     tr[0]=nx;     int t=tr[x].r;     tr[x].r=tr[t].l;     tr[tr[t].l].fa=x;     tr[t].l=x;     tr[t].fa=tr[x].fa;     tr[x].fa=t;     if(tr[x].rt)     {          tr[x].rt=false;          tr[t].rt=true;     }     else     {       if(x==tr[tr[t].fa].l)               tr[tr[t].fa].l=t;          else               tr[tr[t].fa].r=t;     }     push_up(x);}inline void splay(int x){ push(x);     while(!tr[x].rt)     {          int y=tr[x].fa,z=tr[y].fa;          if(tr[y].rt)          {               if(x==tr[y].l)                    zig(y);               else                    zag(y);          }          else if(y==tr[z].l)          {               if(x==tr[y].l){zig(z);zig(y);}               else{zag(y);zig(z);}          }          else          {               if(x==tr[y].r){zag(z);zag(y);}               else{zig(y);zag(z);}          }     }     push_up(x);}inline void access(int x){     int y=0;     while(x!=0)     {          splay(x);          tr[tr[x].r].rt=true;          tr[x].r=y;          tr[y].rt=false;          push_up(x);          y=x;          x=tr[x].fa;     }}inline int findroot(int x){     access(x);     splay(x);     while(tr[x].l!=0)          x=tr[x].l;     return x;}inline bool judge(int s,int t){     s=findroot(s);     t=findroot(t);     if(s==t)          return true;     return false;}inline void mroot(int x){// push_up(x);     access(x);     splay(x);     update_rev(x);}inline void link(int s,int t){     if(judge(s,t))          return ;     mroot(s);     tr[s].fa=t;     //access(s);}inline void cut(int s,int t){     if(s==t||!judge(s,t))          return ;     mroot(s);     access(t);     splay(t);     tr[tr[t].l].fa=0;     tr[tr[t].l].rt=true;     tr[t].l=0;     push_up(t);}inline int ask(int x,int y){     mroot(x);     access(y);     splay(y);     return (tr[tr[y].l].val+val[y])%mod;}inline int add1(int x,int y,unsigned int xx){     mroot(x);     access(y);     splay(y);     val[y]=(val[y]+xx)%mod;     val[tr[y].l]=(val[tr[y].l]+xx)%mod;     tr[tr[y].l].val=(tr[tr[y].l].val+tr[tr[y].l].sz*xx%mod)%mod;     tr[tr[y].l].tag=(tr[tr[y].l].tag+xx)%mod;     push_up(y);     /*tr[tr[y].l].tag=(tr[tr[y].l].tag+xx)%mod;     tr[tr[y].r].tag=(tr[tr[y].r].tag+xx)%mod;*/}inline int add2(int x,int y,unsigned int xx){     mroot(x);     access(y);     splay(y);     val[y]=(val[y]*xx)%mod;     val[tr[y].l]=(val[tr[y].l]*xx)%mod;     tr[tr[y].l].val=tr[tr[y].l].val*xx%mod;     tr[tr[y].l].tag=(tr[tr[y].l].tag*xx)%mod;     tr[tr[y].l].tagx=(tr[tr[y].l].tagx*xx)%mod;     push_up(y); /*    tr[tr[y].l].tagx=(tr[tr[y].l].tagx*xx)%mod;     tr[tr[y].r].tagx=(tr[tr[y].r].tagx*xx)%mod;*/}int main(){//     freopen("data.in","r",stdin);//     freopen("data.out","w",stdout);     int m;     scanf("%d%d",&n,&m);     int i;     int s,t,x;     for(i=1;i<=n-1;i++)          scanf("%d%d",&a[i].s,&a[i].t);     for(i=1;i<=n;i++)     {          val[i]=1;          tr[i].val=val[i];          tr[i].sz=1;          tr[i].rt=true;          tr[i].tagx=1;     }     for(i=1;i<=n-1;i++)          link(a[i].s,a[i].t);     char xx[11];     int s1,t1;     for(i=1;i<=m;i++)     {          scanf("%s",xx);          if(xx[0]=='+')          {               scanf("%d%d%d",&s,&t,&s1);               add1(s,t,s1);          }          else if(xx[0]=='-')          {               scanf("%d%d%d%d",&s,&t,&s1,&t1);               cut(s,t);               link(s1,t1);          }          else if(xx[0]=='*')          {               scanf("%d%d%d",&s,&t,&s1);               add2(s,t,s1);          }          else          {               scanf("%d%d",&s,&t);               printf("%u\n",ask(s,t));          }     }     return 0;}


0 0
原创粉丝点击