bzoj 2631: tree

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值