WZJ的数据结构(负十九) |
难度级别:E; 运行时间限制:3500ms; 运行空间限制: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树全都搞定啦。(我如果把switch改成二分查找会不会快一点呢哈哈)
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 static 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 static 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 add(snode*x,snode*&y,info tag){ 121 x->init();x->x=tag;x->ch[0]=y;if(y)y->fa=x;x->update();y=x;return; 122 } 123 void detach(node*x){ 124 add(x->ch[1]->s[0]->id+Splay,root[x->id],x->ch[1]->all);return; 125 } 126 void connect(node*x,node*y){ 127 snode*p=y->s[0]->id+Splay;splay(p); 128 if(p->ch[0]) p->ch[0]->fa=NULL; 129 if(p->ch[1]) p->ch[1]->fa=NULL; 130 root[x->id]=join(p->ch[0],p->ch[1]); 131 y->chat(p->all);y->tret(p->all);return; 132 } 133 node*access(node*x){ 134 node*ret=NULL; 135 for(;x;x=x->fa){ 136 if(splay(x)->ch[1]) detach(x); 137 if(x->ch[1]=ret) connect(x,ret); 138 (ret=x)->update(); 139 } return ret; 140 } 141 void makeroot(int x){access(x+lct)->revt();return;} 142 void link(int x,int y){ 143 access(lct+y);splay(lct+y)->ch[1]=lct+x;makeroot(x);splay(lct+x)->fa=lct+y;return; 144 } 145 node*findfa(node*x){ 146 x=splay(x)->ch[0]; 147 if(!x) return x; 148 else return x->s[1]; 149 } 150 int queryfa(int x){ 151 node*t;access(x+lct); 152 if(!(t=findfa(x+lct))) return -1; 153 else return t->x.sm; 154 } 155 int treeroot; 156 node*findtop(node*x){return splay(x)->s[0];} 157 bool insub(int x,int y){ 158 if(x==y||x==treeroot) return true; 159 access(y+lct);if(findtop(x+lct)==findtop(y+lct)) return true; 160 return false; 161 } 162 void changesub(int x,int y,tag t){ 163 makeroot(x);access(lct+y);splay(lct+y); 164 lct[y].x=lct[y].x+t; 165 if(root[y]) root[y]->addt(t); 166 lct[y].update();return; 167 } 168 void changecha(int x,int y,tag t){ 169 makeroot(x);access(lct+y)->chat(t);return; 170 } 171 info querycha(int x,int y){ 172 makeroot(x);return access(lct+y)->sm; 173 } 174 info querysub(int x,int y){ 175 makeroot(x);access(lct+y);splay(lct+y);return root[y]?lct[y].x+root[y]->sm:lct[y].x; 176 } 177 void cutfa(int x){ 178 node*t=(access(lct+x),splay(lct+x)); 179 t->ch[0]=t->ch[0]->fa=NULL;t->update();return; 180 } 181 void linkfa(int x,int fa){ 182 access(fa+lct);splay(lct+fa);makeroot(x);splay(lct+x)->fa=lct+fa;lct[fa].update(); 183 add(Splay+x,root[fa],lct[x].all); 184 return; 185 } 186 void splitfa(int r,int x,int fa){ 187 makeroot(r);if((access(lct+x),access(lct+fa))==lct+x) return; 188 cutfa(x);linkfa(x,fa);return; 189 } 190 int n,Q,p1[maxn],p2[maxn],A[maxn]; 191 void inittree(int*a){ 192 for(int i=1;i<=n;i++){ 193 lct[i].id=i; 194 lct[i].s[0]=lct[i].s[1]=lct+i; 195 lct[i].x=lct[i].sm=lct[i].all=(info){a[i],a[i],1,a[i]}; 196 lct[i].cha=lct[i].tre=nulltag; 197 } return; 198 } 199 inline int read(){ 200 int x=0,sig=1;char ch=getchar(); 201 while(!isdigit(ch)){if(ch=='-')sig=-1;ch=getchar();} 202 while(isdigit(ch))x=10*x+ch-'0',ch=getchar(); 203 return x*=sig; 204 } 205 inline void write(long long x){ 206 if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x; 207 int len=0;static long long buf[20];while(x)buf[len++]=x%10,x/=10; 208 for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return; 209 } 210 void init(){ 211 n=read();Q=read(); 212 for(int i=2;i<=n;i++) p1[i]=read(),p2[i]=read(); 213 for(int i=1;i<=n;i++) A[i]=read(); 214 inittree(A); 215 for(int i=2;i<=n;i++) link(p1[i],p2[i]); 216 treeroot=read();makeroot(treeroot); 217 return; 218 } 219 void work(){ 220 int x,y,z,tp; 221 while(Q--){ 222 tp=read();x=read(); 223 switch(tp){ 224 case 0: 225 makeroot(x),treeroot=x; 226 break; 227 case 1: 228 changecha(x,x,(tag){0,read()}); 229 break; 230 case 2: 231 changecha(x,x,(tag){1,read()}); 232 break; 233 case 3: 234 changecha(x,x,(tag){read(),0}); 235 break; 236 case 4: 237 write(querycha(x,x).mi);ENT; 238 break; 239 case 5: 240 y=read();changecha(x,y,(tag){0,read()}); 241 break; 242 case 6: 243 y=read();changecha(x,y,(tag){1,read()}); 244 break; 245 case 7: 246 y=read();changecha(x,y,(tag){read(),0}); 247 break; 248 case 8: 249 y=read();write(querycha(x,y).mi);ENT; 250 break; 251 case 9: 252 y=read();write(querycha(x,y).mx);ENT; 253 break; 254 case 10: 255 y=read();write(querycha(x,y).sm);ENT; 256 break; 257 case 11: 258 y=read();write(querycha(x,y).siz);ENT; 259 break; 260 case 12: 261 changesub(treeroot,x,(tag){0,read()}); 262 break; 263 case 13: 264 changesub(treeroot,x,(tag){1,read()}); 265 break; 266 case 14: 267 changesub(treeroot,x,(tag){read(),0}); 268 break; 269 case 15: 270 write(querysub(treeroot,x).mi);ENT; 271 break; 272 case 16: 273 write(querysub(treeroot,x).mx);ENT; 274 break; 275 case 17: 276 write(querysub(treeroot,x).sm);ENT; 277 break; 278 case 18: 279 write(querysub(treeroot,x).siz);ENT; 280 break; 281 case 19: 282 y=read();splitfa(treeroot,x,y); 283 break; 284 case 20: 285 y=read();if(insub(x,y)) puts("true");else puts("false"); 286 break; 287 case 21: 288 write(queryfa(x));ENT; 289 break; 290 } 291 } 292 return; 293 } 294 void print(){ 295 return; 296 } 297 int main(){init();work();print();return 0;}