2016-06-01 08:50:36

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2631

注意加和乘的标记下传问题。

还有就是split后,要分清x和y哪个是祖先。

pushup在access和rotate后都要进行。

这题还卡常数,开ll就会T,开unsigned int即可。

  1 #include<bits/stdc++.h>
  2 #define inf 1000000000
  3 #define uint unsigned int
  4 #define N 100005
  5 #define mod 51061
  6 using namespace std;
  7 int read(){
  8   int x=0,f=1;char ch=getchar();
  9   while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 10   while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 11   return x*f;
 12 }
 13 int n,q;
 14 char ch[5];
 15 namespace LCT{
 16   int ch[N][2],fa[N],sz[N];bool rev[N];
 17   uint cj[N],add[N],val[N],sum[N];
 18   inline bool isroot(int x){
 19     if(ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x)return 1;return 0;
 20   }
 21   void change(int x,int c,int a){
 22     if(!x)return;
 23     val[x]=(val[x]*c+a)%mod;
 24     sum[x]=(sum[x]*c+a*sz[x])%mod;
 25     add[x]=(add[x]*c+a)%mod;
 26     cj[x]=(cj[x]*c)%mod;
 27   }
 28   void pushdown(int x){
 29     if(rev[x]){
 30       rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;rev[x]^=1;
 31       swap(ch[x][0],ch[x][1]);
 32     }
 33     if(cj[x]!=1||add[x]!=0){
 34       change(ch[x][0],cj[x],add[x]);
 35       change(ch[x][1],cj[x],add[x]);
 36     }
 37     cj[x]=1;add[x]=0;
 38   }
 39   void Pushdown(int x){
 40     if(!isroot(x))Pushdown(fa[x]);
 41     pushdown(x);
 42   }
 43   void pushup(int x){
 44     sum[x]=(sum[ch[x][0]]+sum[ch[x][1]]+val[x])%mod;
 45     sz[x]=(sz[ch[x][0]]+sz[ch[x][1]]+1)%mod;
 46   }
 47   void rotate(int x){
 48     int y=fa[x],k=ch[y][1]==x;
 49     if(!isroot(y))ch[fa[y]][ch[fa[y]][1]==y]=x;
 50     fa[x]=fa[y];
 51     fa[ch[x][!k]]=y;
 52     fa[y]=x;
 53     ch[y][k]=ch[x][!k];
 54     ch[x][!k]=y;
 55     pushup(y);pushup(x);
 56   }
 57   void splay(int x){
 58     Pushdown(x);
 59     for(int y=fa[x];!isroot(x);y=fa[x]){
 60       if(!isroot(y)){
 61         if((ch[fa[y]][ch[fa[y]][1]==y])!=(ch[y][1]==x))rotate(x);
 62         else rotate(y);
 63       }rotate(x);
 64     }
 65   }
 66   inline void access(int x){
 67     int y=0;
 68     while(x){
 69       splay(x);
 70       ch[x][1]=y;pushup(x);
 71       x=fa[y=x];
 72     }
 73   }
 74   inline void moveroot(int x){
 75     access(x);splay(x);rev[x]^=1;
 76   }
 77   inline void link(int x,int y){
 78     moveroot(x);fa[x]=y;splay(x);
 79   }
 80   inline void cut(int x,int y){
 81     moveroot(x);access(y);splay(y);ch[y][0]=fa[x]=0;
 82   }
 83   inline void split(int x,int y){
 84     moveroot(y);access(x);splay(x);
 85   }
 86 }
 87 int main(){
 88   n=read();q=read();
 89   for(int i=1;i<=n;i++)LCT::val[i]=LCT::sum[i]=LCT::cj[i]=LCT::sz[i]=1;
 90   for(int i=1;i<n;i++)LCT::link(read(),read());
 91   while(q--){
 92     scanf("%s",ch);
 93     int u=read(),v=read();
 94     if(ch[0]=='+')LCT::split(u,v),LCT::change(u,1,read());
 95     else if(ch[0]=='-'){
 96       LCT::cut(u,v);u=read();v=read();LCT::link(u,v);
 97     }
 98     else if(ch[0]=='*')LCT::split(u,v),LCT::change(u,read(),0);
 99     else LCT::split(u,v),printf("%d\n",LCT::sum[u]%mod);
100   }
101   return 0;
102 }
View Code

相关文章: