BZOJ2631: tree(LCT)

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

解题思路:

假如没有2操作,且图是树,是不是想起了线段树。

这道题也是一样的道理,LCT嘛,splay维护树链

代码:

  1 // luogu-judger-enable-o2
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define lll tr[spc].ch[0]
  6 #define rrr tr[spc].ch[1]
  7 #define ls ch[0]
  8 #define rs ch[1]
  9 typedef unsigned int lnt;
 10 const lnt mod=51061;
 11 struct trnt{
 12     int ch[2];
 13     int fa;
 14     int lzt;
 15     lnt add;
 16     lnt mul;
 17     lnt sum;
 18     lnt wgt;
 19     lnt val;
 20     bool anc;
 21 }tr[100005];
 22 int st[100001];
 23 int tp;
 24 int n,q;
 25 char cmd[10];
 26 int read()
 27 {
 28     int f=1,x=0;
 29     char ss=getchar();
 30     while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
 31     while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
 32     return f*x;
 33 }
 34 int comd(void)
 35 {
 36     if(cmd[0]=='+')
 37         return 1;
 38     if(cmd[0]=='-')
 39         return 2;
 40     if(cmd[0]=='*')
 41         return 3;
 42     if(cmd[0]=='/')
 43         return 4;
 44     return 0;
 45 }
 46 bool whc(int spc)
 47 {
 48     return tr[tr[spc].fa].rs==spc;
 49 }
 50 void pushup(int spc)
 51 {
 52     tr[spc].wgt=tr[lll].wgt+tr[rrr].wgt+1;
 53     tr[spc].sum=(tr[lll].sum+tr[rrr].sum+tr[spc].val)%mod;
 54 }
 55 void trr(int spc)
 56 {
 57     if(!spc)
 58         return ;
 59     tr[spc].lzt^=1;
 60     std::swap(lll,rrr);
 61 }
 62 void Mul(int spc,lnt k)
 63 {
 64     if(!spc)
 65         return ;
 66     tr[spc].add=tr[spc].add*k%mod;
 67     tr[spc].sum=tr[spc].sum*k%mod;
 68     tr[spc].val=tr[spc].val*k%mod;
 69     tr[spc].mul=tr[spc].mul*k%mod;
 70 }
 71 void Add(int spc,lnt k)
 72 {
 73     if(!spc)
 74         return ;
 75     if(tr[spc].mul)
 76     {
 77         Mul(lll,tr[spc].mul);
 78         Mul(rrr,tr[spc].mul);
 79         tr[spc].mul=1;
 80     }
 81     tr[spc].sum=(tr[spc].sum+tr[spc].wgt*k)%mod;
 82     tr[spc].val=(tr[spc].val+k)%mod;
 83     tr[spc].add=(tr[spc].add+k)%mod;
 84 }
 85 void pushdown(int spc)
 86 {
 87     if(tr[spc].lzt)
 88     {
 89         tr[spc].lzt=0;
 90         trr(lll);
 91         trr(rrr);
 92     }
 93     if(tr[spc].mul!=1)
 94     {
 95         Mul(lll,tr[spc].mul);
 96         Mul(rrr,tr[spc].mul);
 97         tr[spc].mul=1;
 98     }
 99     if(tr[spc].add)
100     {
101         Add(lll,tr[spc].add);
102         Add(rrr,tr[spc].add);
103         tr[spc].add=0;
104     }
105 }
106 void rotate(int spc)
107 {
108     int f=tr[spc].fa;
109     bool k=whc(spc);
110     tr[f].ch[k]=tr[spc].ch[!k];
111     tr[spc].ch[!k]=f;
112     if(tr[f].anc)
113     {
114         tr[spc].anc=1;
115         tr[f].anc=0;
116     }else
117         tr[tr[f].fa].ch[whc(f)]=spc;
118     tr[spc].fa=tr[f].fa;
119     tr[f].fa=spc;
120     tr[tr[f].ch[k]].fa=f;
121     pushup(f);
122     pushup(spc);
123 }
124 void splay(int spc)
125 {
126     tp=0;
127     int x=spc;
128     while(!tr[x].anc)
129         st[++tp]=x,x=tr[x].fa;
130     st[++tp]=x;
131     while(tp)
132         pushdown(st[tp--]);
133     while(!tr[spc].anc)
134     {
135         int ft=tr[spc].fa;
136         if(tr[ft].anc)
137         {
138             rotate(spc);
139             return ;
140         }
141         if(whc(spc)^whc(ft))
142             rotate(spc);
143         else
144             rotate(ft);
145         rotate(spc);
146     }
147     pushup(spc);
148 }
149 void access(int spc)
150 {
151     int lst=0;
152     while(spc)
153     {
154         splay(spc);
155         tr[rrr].anc=1;
156         tr[lst].anc=0;
157         rrr=lst;
158         pushup(spc);
159         lst=spc;
160         spc=tr[spc].fa;
161     }
162 }
163 void Mtr(int spc)
164 {
165     access(spc);
166     splay(spc);
167     trr(spc);
168 }
169 void split(int x,int y)
170 {
171     Mtr(x);
172     access(y);
173     splay(y);
174 }
175 void link(int x,int y)
176 {
177     Mtr(x);
178     tr[x].fa=y;
179 }
180 void cut(int x,int y)
181 {
182     split(x,y);
183     tr[y].ls=0;
184     tr[x].fa=0;
185     tr[x].anc=1;
186     pushup(y);
187 }
188 int main()
189 {
190     n=read();
191     q=read();
192     for(int i=1;i<=n;i++)
193     {
194         tr[i].anc=1;
195         tr[i].mul=1;
196         tr[i].val=1;
197         tr[i].wgt=tr[i].sum=1;
198     }
199     for(int i=1;i<n;i++)
200     {
201         int a=read(),b=read();
202         link(a,b);
203     }
204     while(q--)
205     {
206         scanf("%s",cmd);
207         int opt=comd();
208         if(opt==1)
209         {
210             int u=read(),v=read(),c=read();
211             split(u,v);
212             Add(v,c);
213         }
214         if(opt==2)
215         {
216             int ua=read(),va=read(),ub=read(),vb=read();
217             cut(ua,va);
218             link(ub,vb);
219         }
220         if(opt==3)
221         {
222             int u=read(),v=read(),c=read();
223             split(u,v);
224             Mul(v,c);
225         }
226         if(opt==4)
227         {
228             int u=read(),v=read();
229             split(u,v);
230             printf("%u\n",tr[v].sum);
231         }
232     }
233     return 0;
234 }

 

posted @ 2018-09-13 12:55  Unstoppable728  阅读(191)  评论(0编辑  收藏  举报