COJ 0981 WZJ的数据结构(负十九)树综合

WZJ的数据结构(负十九)
难度级别:E; 运行时间限制:15000ms; 运行空间限制:262144KB; 代码长度限制:2000000B

试题描述

WZJ的数据结构中有很多都是关于树的。这让很多练习模板的同学还要找来找去很不爽,于是WZJ跟小伙伴们一块商量如何将这些题汇拢到一块去:

WZJ:为了大家简单,我规定一开始是一棵有根树。

LZJ:那我一定得加上换根操作喽。

XJR:链信息修改,链信息增加,链信息翻倍,维护链信息的最大,最小,总和肯定很好做。

CHX:子树信息修改,子树信息增加,子树信息翻倍,维护子树信息的最大,最小,总和肯定也很好做。

WZJ:那这道题太水了吧,我们要能随时改变树的形态多好,加个换父亲的操作吧。

CHX:那也够水的,咱们再加一个查询父亲的操作吧。

LZJ:好不容易出了一道综合题,再加一个查询是否在子树内的操作吧。

XJR:一定要卡掉离线是必须的吧?


输入

本题一共有22个操作:
第一行是N和M,表示有这棵树有N个点M个询问
然后是N-1行,每行x,y表示x-y有一条边
接下去是N行,每行是一个数字,表示每个点的权值
后面一行表示根
接下来是M行
第一个数字是K
K=0 表示换根,后面x,表示把这棵树的根变成x
K=1 表示点修改,后面x,y 表示把点x的权值改为y
K=2 表示点增加,后面x,y 表示把点x的权值增加y
K=3 表示点翻倍,后面x,y 表示把点x的权值翻y倍
K=4 表示点询问权值,后面x 表示询问这个点的权值
K=5 表示链修改,后面x,y,z,表示把这棵树中x-y的路径上点权值改成z
K=6 表示链增加,后面x,y,z,表示把这棵树中x-y的路径上点权值增加z
K=7 表示链翻倍,后面x,y,z,表示把这棵树中x-y的路径上点权值翻z倍
K=8 表示链询问min,后面x,y,表示询问这棵树中x-y的路径上点的min
K=9 表示链询问max,后面x,y,表示询问这棵树中x-y的路径上点的max
K=10 表示链询问sum,后面x,y,表示询问这棵树中x-y的路径上点的sum
K=11 表示链询问siz,后面x,y,表示询问这棵树中x-y的路径上点的多少
K=12 表示子树修改,后面x,y,表示以x为根的子树的点权值改成y
K=13 表示子树增加,后面x,y,表示以x为根的子树的点权值增加y
K=14 表示子树翻倍,后面x,y,表示以x为根的子树的点权值翻y倍
K=15 表示子树询问min,后面x,表示询问以x为根的子树的点的min
K=16 表示子树询问max,后面x,表示询问以x为根的子树的点的max
K=17 表示子树询问sum,后面x,表示询问以x为根的子树的点的sum
K=18 表示子树询问siz,后面x,表示询问以x为根的子树的点的多少
K=19 表示换父亲,后面x,y,表示把x的父亲换成y,如果y在x子树里不操作
K=20 表示询问子树,后面x,y, 表示询问y是否在x的子树内,输出true/false
K=21 表示查询父亲,后面x,表示询问x的父亲的点权值,若没有父亲则输出-1

输出

对于每个询问输出一个答案,一行一个。

输入示例

5 30
1 2
2 3
3 4
4 5
1 -2 3 -1 2
3
0 2
1 2 2
2 3 1
3 5 5
4 2
5 3 2 5
6 1 4 3
7 4 5 2
8 5 3
9 2 5
10 1 5
11 3 4
12 4 -3
13 2 -1
14 3 4
15 2
16 2
17 4
18 4
19 4 1
20 1 4
21 1
14 1 4
15 3
18 1
19 5 3
21 5
13 3 1
4 5
17 2

输出示例

2
4
20
44
2
-16
28
-32
2
true
7
28
3
28
-63
-79

其他说明

N,M<=100000,所有计算结果保证在long long范围之内。

题解:水水哒AAA树全都搞定啦。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<cstring>
  7 #define PAU putchar(‘ ‘)
  8 #define ENT putchar(‘\n‘)
  9 #define CH for(int d=0;d<=1;d++) if(ch[d])
 10 using namespace std;
 11 const int maxn=100000+10,inf=1<<29;
 12 struct info{long long mi,mx,siz,sm;}null=(info){inf,-inf,0,0};
 13 struct tag{int mul,add;bool empty(){return (mul==1&&add==0);}}nulltag=(tag){1,0};
 14 info operator+(const info&a,const info&b){
 15     return (info){min(a.mi,b.mi),max(a.mx,b.mx),a.siz+b.siz,a.sm+b.sm};
 16 }
 17 info operator+(const info&a,const tag&b){
 18     return a.siz?(info){a.mi*b.mul+b.add,a.mx*b.mul+b.add,a.siz,a.sm*b.mul+b.add*a.siz}:null;
 19 }
 20 tag operator+(const tag&a,const tag&b){
 21     return (tag){a.mul*b.mul,a.add*b.mul+b.add};
 22 }
 23 struct snode{
 24     snode*ch[2],*fa;
 25     info x,sm;tag od,all;
 26     void init(){x=sm=null;od=all=nulltag;ch[0]=ch[1]=fa=NULL;return;}
 27     snode(){x=sm=null;od=all=nulltag;ch[0]=ch[1]=fa=NULL;}
 28     void addt(tag a){
 29         od=od+a;all=all+a;x=x+a;sm=sm+a;return;
 30     }
 31     void down(){
 32         if(!od.empty()){CH{ch[d]->addt(od);};od=nulltag;}return;
 33     }
 34     void update(){
 35         sm=x;CH{sm=sm+ch[d]->sm;}return;
 36     }
 37 }Splay[maxn],*root[maxn];
 38 int parent(snode*x,snode*&y){return (y=x->fa)?y->ch[1]==x?1:y->ch[0]==x?0:-1:-1;}
 39 void rotate(snode*x){
 40     snode*y,*z;int d1=parent(x,y),d2=parent(y,z);
 41     if(y->ch[d1]=x->ch[d1^1]) y->ch[d1]->fa=y;
 42     y->fa=x;x->fa=z;x->ch[d1^1]=y;
 43     if(d2!=-1) z->ch[d2]=x;
 44     y->update();return;
 45 }
 46 void pushdown(snode*x){
 47     static snode*s[maxn];int top=0;
 48     for(snode*y;;x=y){
 49         s[top++]=x;y=x->fa;
 50         if(!y||(y->ch[0]!=x&&y->ch[1]!=x)) break;
 51     } while(top--) s[top]->down();return;
 52 }
 53 snode*splay(snode*x){
 54     pushdown(x);snode*y,*z;int d1,d2;
 55     while(true){
 56         if((d1=parent(x,y))<0) break;
 57         if((d2=parent(y,z))<0){rotate(x);break;}
 58         if(d1==d2) rotate(y),rotate(x);
 59         else rotate(x),rotate(x);
 60     } x->update();return x;
 61 }
 62 snode*join(snode*x,snode*y){
 63     if(!x)return y;if(!y)return x;
 64     while(x->ch[1]) x->down(),x=x->ch[1];
 65     splay(x)->ch[1]=y;y->fa=x;x->update();return x;
 66 }
 67 struct node{
 68     node*ch[2],*fa,*s[2];
 69     info x,sm,sb,all;tag cha,tre;bool rev;
 70     int id;
 71     void revt(){
 72         swap(ch[0],ch[1]);swap(s[0],s[1]);rev^=1;return;
 73     }
 74     void chat(tag a){
 75         x=x+a;sm=sm+a;cha=cha+a;all=sm+sb;return;
 76     }
 77     void tret(tag a){
 78         tre=tre+a;sb=sb+a;all=sm+sb;if(root[id])root[id]->addt(a);return;
 79     }
 80     void down(){
 81         if(rev){CH{ch[d]->revt();}rev=false;}
 82         if(!cha.empty()){CH{ch[d]->chat(cha);}cha=nulltag;}
 83         if(!tre.empty()){CH{ch[d]->tret(tre);}tre=nulltag;}
 84         return;
 85     }
 86     void update(){
 87         sm=x;sb=null;
 88         if(root[id])sb=sb+root[id]->sm;
 89         CH{sm=sm+ch[d]->sm;sb=sb+ch[d]->sb;}
 90         all=sm+sb;
 91         s[0]=ch[0]?ch[0]->s[0]:this;
 92         s[1]=ch[1]?ch[1]->s[1]:this;
 93         return;
 94     }
 95 }lct[maxn];
 96 int parent(node*x,node*&y){return (y=x->fa)?y->ch[1]==x?1:y->ch[0]==x?0:-1:-1;}
 97 void rotate(node*x){
 98     node*y,*z;int d1=parent(x,y),d2=parent(y,z);
 99     if(y->ch[d1]=x->ch[d1^1]) y->ch[d1]->fa=y;
100     y->fa=x;x->fa=z;x->ch[d1^1]=y;
101     if(d2!=-1) z->ch[d2]=x;
102     y->update();return;
103 }
104 void pushdown(node*x){
105     static node*s[maxn];int top=0;
106     for(node*y;;x=y){
107         s[top++]=x;y=x->fa;
108         if(!y||(y->ch[0]!=x&&y->ch[1]!=x)) break;
109     } while(top--) s[top]->down();return;
110 }
111 node*splay(node*x){
112     pushdown(x);node*y,*z;int d1,d2;
113     while(true){
114         if((d1=parent(x,y))<0) break;
115         if((d2=parent(y,z))<0){rotate(x);break;}
116         if(d1==d2) rotate(y),rotate(x);
117         else rotate(x),rotate(x);
118     } x->update();return x;
119 }
120 void detach(node*x){
121     snode*p=x->ch[1]->s[0]->id+Splay;p->init();
122     p->x=x->ch[1]->all;x->ch[1]=NULL;
123     int id=x->id;
124     p->ch[0]=root[id];
125     if(root[id]) root[id]->fa=p;
126     p->update();root[id]=p;return;
127 }
128 void connect(node*x,node*y){
129     snode*p=y->s[0]->id+Splay;
130     int id=x->id;splay(p);
131     if(p->ch[0]) p->ch[0]->fa=NULL;
132     if(p->ch[1]) p->ch[1]->fa=NULL;
133     root[id]=join(p->ch[0],p->ch[1]);
134     y->chat(p->all);y->tret(p->all);return;
135 }
136 node*access(node*x){
137     node*ret=NULL;
138     for(;x;x=x->fa){
139         splay(x);if(x->ch[1]) detach(x);
140         x->ch[1]=ret;if(ret) connect(x,ret);
141         (ret=x)->update();
142     } return ret;
143 }
144 void makeroot(int x){access(x+lct)->revt();return;}
145 void link(int x,int y){
146     makeroot(x);splay(lct+x)->fa=lct+y;
147     access(lct+y);splay(lct+y)->ch[1]=lct+x;
148     return;
149 }
150 node*findfa(node*x){
151     access(x);x=splay(x)->ch[0];
152     if(!x) return x;
153     else return x->s[1];
154 }
155 int queryfa(int x){
156     node*t;
157     if(!(t=findfa(x+lct))) return -1;
158     else return t->x.sm;
159 }
160 int treeroot;
161 bool insub(int x,int y){
162     if(x==y||x==treeroot) return true;
163     makeroot(treeroot);node*t=y+lct;access(t);splay(t);
164     while(t->ch[0]){
165         t=splay(splay(t)->ch[0]->s[1]);
166         if(t==x+lct) return true;
167     } return false;
168 }
169 void changesub(int x,int y,tag t){
170     makeroot(x);access(lct+y);splay(lct+y);
171     lct[y].x=lct[y].x+t;
172     if(root[y]) root[y]->addt(t);
173     lct[y].update();return;
174 }
175 void changecha(int x,int y,tag t){
176     makeroot(x);access(lct+y)->chat(t);return;
177 }
178 info querycha(int x,int y){
179     makeroot(x);return access(lct+y)->sm;
180 }
181 info querysub(int x,int y){
182     makeroot(x);access(lct+y);splay(lct+y);return root[y]?lct[y].x+root[y]->sm:lct[y].x;
183 }
184 void cutfa(int x){
185     node*t=(access(lct+x),splay(lct+x));
186     t->ch[0]=t->ch[0]->fa=NULL;t->update();return;
187 }
188 void linkfa(int x,int fa){
189     access(fa+lct);splay(lct+fa);
190     makeroot(x);splay(lct+x)->fa=lct+fa;lct[fa].update();
191     snode*p=Splay+x;p->init();p->x=lct[x].all;
192     p->ch[0]=root[fa];if(root[fa]) root[fa]->fa=p;
193     root[fa]=p;p->update();return;
194 }
195 void splitfa(int r,int x,int fa){
196     makeroot(r);if((access(lct+x),access(lct+fa))==lct+x) return;
197     cutfa(x);linkfa(x,fa);return;
198 }
199 int n,Q,p1[maxn],p2[maxn],A[maxn];
200 void inittree(int*a){
201     for(int i=1;i<=n;i++){
202         lct[i].id=i;
203         lct[i].s[0]=lct[i].s[1]=lct+i;
204         lct[i].x=lct[i].sm=lct[i].all=(info){a[i],a[i],1,a[i]};
205         lct[i].cha=lct[i].tre=nulltag;
206     } return;
207 }
208 inline int read(){
209     int x=0,sig=1;char ch=getchar();
210     while(!isdigit(ch)){if(ch==‘-‘)sig=-1;ch=getchar();}
211     while(isdigit(ch))x=10*x+ch-‘0‘,ch=getchar();
212     return x*=sig;
213 }
214 inline void write(long long x){
215     if(x==0){putchar(‘0‘);return;}if(x<0)putchar(‘-‘),x=-x;
216     int len=0;static long long buf[20];while(x)buf[len++]=x%10,x/=10;
217     for(int i=len-1;i>=0;i--)putchar(buf[i]+‘0‘);return;
218 }
219 void init(){
220     n=read();Q=read();
221     for(int i=2;i<=n;i++) p1[i]=read(),p2[i]=read();
222     for(int i=1;i<=n;i++) A[i]=read();
223     inittree(A);
224     for(int i=2;i<=n;i++) link(p1[i],p2[i]);
225     treeroot=read();makeroot(treeroot);
226     return;
227 }
228 void work(){
229     int x,y,z,tp;
230     while(Q--){
231         tp=read();x=read();
232         switch(tp){
233             case 0:
234                 makeroot(x),treeroot=x;
235                 break;
236             case 1:
237                 changecha(x,x,(tag){0,read()});
238                 break;
239             case 2:
240                 changecha(x,x,(tag){1,read()});
241                 break;
242             case 3:
243                 changecha(x,x,(tag){read(),0});
244                 break;
245             case 4:
246                 write(querycha(x,x).mi);ENT;
247                 break;
248             case 5:
249                 y=read();changecha(x,y,(tag){0,read()});
250                 break;
251             case 6:
252                 y=read();changecha(x,y,(tag){1,read()});
253                 break;
254             case 7:
255                 y=read();changecha(x,y,(tag){read(),0});
256                 break;
257             case 8:
258                 y=read();write(querycha(x,y).mi);ENT;
259                 break;
260             case 9:
261                 y=read();write(querycha(x,y).mx);ENT;
262                 break;
263             case 10:
264                 y=read();write(querycha(x,y).sm);ENT;
265                 break;
266             case 11:
267                 y=read();write(querycha(x,y).siz);ENT;
268                 break;
269             case 12:
270                 changesub(treeroot,x,(tag){0,read()});
271                 break;
272             case 13:
273                 changesub(treeroot,x,(tag){1,read()});
274                 break;
275             case 14:
276                 changesub(treeroot,x,(tag){read(),0});
277                 break;
278             case 15:
279                 write(querysub(treeroot,x).mi);ENT;
280                 break;
281             case 16:
282                 write(querysub(treeroot,x).mx);ENT;
283                 break;
284             case 17:
285                 write(querysub(treeroot,x).sm);ENT;
286                 break;
287             case 18:
288                 write(querysub(treeroot,x).siz);ENT;
289                 break;
290             case 19:
291                 y=read();splitfa(treeroot,x,y);
292                 break;
293             case 20:
294                 y=read();if(insub(x,y)) puts("true");else puts("false");
295                 break;
296             case 21:
297                 write(queryfa(x));ENT;
298                 break;
299         }
300     }
301     return;
302 }
303 void print(){
304     return;
305 }
306 int main(){init();work();print();return 0;}
时间: 2024-10-25 03:25:00

COJ 0981 WZJ的数据结构(负十九)树综合的相关文章

COJ 1010 WZJ的数据结构(十) 线段树区间操作

传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001 WZJ的数据结构(十) 难度级别:D: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,高效执行以下过程: #include<iostream>using namespace std;const int maxn=100010;int A[maxn];int tp,ql,qr,v;int

COJ 1010 WZJ的数据结构(十) 线段树的地狱

传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001 WZJ的数据结构(十) 难度级别:D: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,高效执行以下过程: #include<iostream>using namespace std;const int maxn=100010;int A[maxn];int tp,ql,qr,v;int

19. 蛤蟆的数据结构进阶十九外部排序相关概念

19. 蛤蟆的数据结构进阶十九外部排序相关概念 本篇名言:"一个人最怕不老实,青年人最可贵的是老实作风. "老实 " 就是不自欺欺人,做到不欺骗人家容易,不欺骗自己最难. "老实作风 " 就是脚踏实地,不占便宜.世界上没有便宜的事,谁想占便宜水就会吃亏. --徐特立" 之前我们学习的排序都是内部排序的,接下去来看下外部排序. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47

COJ 0970 WZJ的数据结构(负三十)树分治

WZJ的数据结构(负三十) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,点和边上均有权值.请你设计一个数据结构,回答M次操作. 1 x v:对于树上的每一个节点y,如果将x.y在树上的距离记为d,那么将y节点的权值加上d*v. 2 x:询问节点x的权值. 输入 第一行为一个正整数N.第二行到第N行每行三个正整数ui,vi,wi.表示一条树边从ui到vi,距离为wi.第N+1行为一个正整数M.最后

COJ 0979 WZJ的数据结构(负二十一)

WZJ的数据结构(负二十一) 难度级别:C: 运行时间限制:5000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你实现一个数据结构,完成这样的功能: 给你一个N个点的图,初始状态无边. 每次加入一条双向边(u,v,w),若加入后没有构成一棵生成树,输出“Not Yet”,否则输出当前最小生成树的权值. 输入 第一行两个正整数N,M.表示有N个点M个操作.接下来M行每行三个正整数u,v,w. 输出 每次加入一条双向边(u,v,w),若加入后没有构成一棵生成

COJ 0995 WZJ的数据结构(负五)区间操作

WZJ的数据结构(负五) 难度级别:C: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大小为N的整数组A,要求你回答执行M次操作.操作分两种: 操作1:每次操作给你l,r,v三个参数,求Al至Ar中值<=v的个数. 操作2:每次操作给你l,r,v三个参数,将Al至Ar中每个数的值+v. 输入 第一行为一个正整数N.第二行为N个整数Ai.第三行为一个正整数M.接下来M行每行4个正整数t,l,

COJ 0999 WZJ的数据结构(负一)

WZJ的数据结构(负一) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 输入N个模板串Pi和文本串T,输出每个模板串Pi在T中出现了多少次. 输入 第一行为一个正整数N.接下来N行为Pi.最后一行为T 输出 输出N行,第i行为模板串Pi在T中出现的次数. 输入示例 5aabbaabaaababababa 输出示例 54445 其他说明 1<=sigma(|Pi|)<=10000001<=|T|<=10000

COJ 0967 WZJ的数据结构(负三十三)

WZJ的数据结构(负三十三) 难度级别:E: 运行时间限制:7000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大小为N的整数组A,要求你回答执行N次操作.操作分两种: 操作1:每次操作给你l,r,v三个参数,求Al至Ar中值<=v的个数. 操作2:每次操作给你l,r,v三个参数,将Al至Ar所有数的值设为v. 输入 第一行为一个正整数N.第二行为N个整数Ai.接下来N行每行4个正整数t,l,r,v.若t=2表

COJ 0985 WZJ的数据结构(负十五)(限定区域不同数)

传送门:http://oj.cnuschool.org.cn/oj/home/addSolution.htm?problemID=955 试题描述: CHX有一个问题想问问大家.给你一个长度为N的数列A,请你找到两个位置L,R,使得A[L].A[L+1].…….A[R]中没有重复的数,输出R-L+1的最大值. 以上是附中联赛加试的一道题.WZJ觉得这道题太水了,改了改题目: WZJ有一个问题想问问大家.给你一个长度为N的数列A,你要回答M次问题.每次问题给你两个正整数ql,qr.请你找到两个位置