1. 程式人生 > >SP16580 QTREE7 - Query on a tree VII(LCT)

SP16580 QTREE7 - Query on a tree VII(LCT)

題解 head upd link open hup targe names 了吧

題意翻譯

一棵樹,每個點初始有個點權和顏色(輸入會給你)

0 u:詢問所有u,v路徑上的最大點權,要滿足u,v路徑上所有點顏色相同

1 u:反轉u的顏色

2 u w:把u的點權改成w

題解

Qtree6的升級版,建議先做完再來做這題(畢竟那個代碼改一改就能做這個了兩倍經驗豈不美哉)(Qtree6我的題解->這裏)

我就當你們已經都會Qtree6了(小聲)

就是把Qtree6中維護連通塊中點的個數,變成維護子樹中的最大值就行了

實子樹的max直接用,虛子樹的max可以直接丟進一個set裏

然後就是access的時候虛實邊轉化,set裏要變一下(個人感覺access的時候不需要pushup,因為虛實邊轉化了,子樹最大值是不變的)

然後就是節點0的值賦為-inf省的pushup的時候變為0,因為節點的值會有負的

然後就是update的時候只改一顆樹裏的竟然對了……可能是因為findroot的時候splay過了吧……

  1 //minamoto
  2 #include<bits/stdc++.h>
  3 #define Col lct[col[x]]
  4 #define inf 0x3f3f3f3f
  5 using namespace std;
  6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
  7
char buf[1<<21],*p1=buf,*p2=buf; 8 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} 9 inline int read(){ 10 #define num ch-‘0‘ 11 char ch;bool flag=0;int res; 12 while(!isdigit(ch=getc())) 13 (ch==-)&&(flag=true); 14 for
(res=num;isdigit(ch=getc());res=res*10+num); 15 (flag)&&(res=-res); 16 #undef num 17 return res; 18 } 19 char sr[1<<21],z[20];int C=-1,Z; 20 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} 21 inline void print(int x){ 22 if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x; 23 while(z[++Z]=x%10+48,x/=10); 24 while(sr[++C]=z[Z],--Z);sr[++C]=\n; 25 } 26 const int N=100005; 27 int f[N],Next[N<<1],head[N],ver[N<<1],tot,col[N],n,m,v[N]; 28 inline void add(int u,int v){ 29 ver[++tot]=v,Next[tot]=head[u],head[u]=tot; 30 ver[++tot]=u,Next[tot]=head[v],head[v]=tot; 31 } 32 struct LCT{ 33 int fa[N],ch[N][2],mx[N]; 34 multiset<int> s[N]; 35 LCT(){mx[0]=-inf;} 36 inline bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;} 37 #define lc ch[x][0] 38 #define rc ch[x][1] 39 inline void pushup(int x){ 40 cmax(mx[x]=v[x],max(mx[lc],mx[rc])); 41 if(!s[x].empty()) cmax(mx[x],*s[x].rbegin()); 42 } 43 void rotate(int x){ 44 int y=fa[x],z=fa[y],d=ch[y][1]==x; 45 if(!isroot(y)) ch[z][ch[z][1]==y]=x; 46 fa[x]=z,fa[y]=x,fa[ch[x][d^1]]=y,ch[y][d]=ch[x][d^1],ch[x][d^1]=y,pushup(y); 47 } 48 void splay(int x){ 49 for(int y=fa[x],z=fa[y];!isroot(x);y=fa[x],z=fa[y]){ 50 if(!isroot(y)) 51 ((ch[y][1]==x)^(ch[z][1]==y))?rotate(x):rotate(y); 52 rotate(x); 53 } 54 pushup(x); 55 } 56 void access(int x){ 57 for(int y=0;x;x=fa[y=x]){ 58 splay(x); 59 if(rc) s[x].insert(mx[rc]); 60 if(rc=y) s[x].erase(s[x].find(mx[y])); 61 } 62 } 63 int findroot(int x){ 64 access(x),splay(x); 65 while(lc) x=lc; 66 splay(x); 67 return x; 68 } 69 void link(int x){ 70 access(x),splay(x); 71 int y=fa[x]=f[x]; 72 access(y),splay(y); 73 ch[y][1]=x,pushup(y); 74 } 75 void cut(int x){ 76 access(x),splay(x); 77 lc=fa[lc]=0; 78 pushup(x); 79 } 80 void update(int x){ 81 access(x),splay(x); 82 v[x]=read(),pushup(x); 83 } 84 }lct[2]; 85 void dfs(int x){ 86 for(int i=head[x];i;i=Next[i]){ 87 int v=ver[i]; 88 if(v==f[x]) continue; 89 f[v]=x,dfs(v); 90 } 91 Col.link(x); 92 } 93 int main(){ 94 //freopen("testdata.in","r",stdin); 95 n=read(); 96 for(int i=1;i<n;++i){ 97 int u=read(),v=read(); 98 add(u,v); 99 } 100 for(int i=1;i<=n;++i) col[i]=read(); 101 for(int i=1;i<=n;++i) v[i]=read(); 102 f[1]=n+1,dfs(1); 103 m=read(); 104 while(m--){ 105 int op=read(),x=read(); 106 switch(op){ 107 case 0:print(Col.mx[Col.ch[Col.findroot(x)][1]]);break; 108 case 1:Col.cut(x),col[x]^=1,Col.link(x);break; 109 case 2:Col.update(x);break; 110 } 111 } 112 Ot(); 113 return 0; 114 }

SP16580 QTREE7 - Query on a tree VII(LCT)