COJ 0981 WZJ 의 데이터 구조 (마이너스 19) 트 리 종합

52639 단어 데이터 구조

WZJ 의 데이터 구조 (마이너스 19)
난이도 레벨: E;운행 시간 제한: 3500 ms;운행 공간 제한: 262144KB;코드 길이 제한: 2000000 B
시험 문제 설명
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 뿌리 를 바꾸다
K=1 고치다 점 x 의 가중치 를 y 로 바 꾸 는 것 을 나타 낸다.
K=2 더 하 다 점 x 의 가중치 를 y 증가 시 키 는 것 을 나타 낸다.
K=3 에서 점 x 의 가중치 를 y 배로 늘 리 는 것 을 나타 낸다.
K=4 질문 이 점 의 가 치 를 묻 는 것 을 나타 낸다.
K=5 체인 수정, 뒤에 x, y, z 를 표시 합 니 다. 이 나무 에서 x - y 의 경로 상 점 값 을 z 로 바 꾸 는 것 을 표시 합 니 다.
K=6 체인 증가, 뒤에 x, y, z 를 표시 합 니 다.
K=7 이 나무 에서 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 를 표시 합 니 다.
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 하면, 만약, 만약...
K=20 하위 트 리, 뒤에 x, y, y 가 x 의 하위 트 리 에 있 는 지 물 어보 고 true / false 를 출력 합 니 다.
K=21 아버지
출력
질문 마다 답 을 하나씩 출력 합 니 다.
예제 입력
5 301 22 33 44 51 -2 3 -1 230 21 2 22 3 13 5 54 25 3 2 56 1 4 37 4 5 28 5 39 2 510 1 511 3 412 4 -313 2 -114 3 415 216 217 418 419 4 120 1 421 114 1 415 318 119 5 321 513 3 14 517 2
출력 예시
2420442-1628-322true728328-63-79
기타 설명
N, M < = 100000, 모든 계산 결 과 는 log 로 보장 합 니 다. long 범위 내.
문제 풀이: 물이 야. AAA 나무 다 됐어.(내 가 switch 를 2 점 으로 바 꿔 서 찾 으 면 좀 빠 르 지 않 을 까 하하)
  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('
') 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;}

좋은 웹페이지 즐겨찾기