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