SPOJ2939 QTREE5(LCT維護子樹資訊)
阿新 • • 發佈:2018-12-22
QWQ嚶嚶嚶
此題正規題解應該是邊分治??或者是樹剖(總之不是LCT)
但是我這裡還是把它當成一個LCT題目來做
首先,這個題的重點還是在update上
因為有\(makeroot\)這個操作的存在,所以自然避免不了\(reverse\),而當\(reverse\)之後,會影響到每個點維護的值的時候,就需要同時維護兩個相反的陣列,在\(reverse\)的時候,直接\(swap\)
對於本題來說,我們對於一個點需要維護一個虛子樹的\(maxdis\) (這裡需要\(multiset\)來維護,因為access的時候,涉及到修改的問題)
一個到深度最淺的點的\(ans1\),到深度最深的點的\(ans2\)
考慮轉移,ans1的轉移顯然可以由\(ans1[ch[x][0]]\)轉移而來(表示左子樹內部的路徑),其次,他還可以從\(min(fir(s[x]),ans1[ch[x][1]])+val[x]+val[ch[x][0]\)轉移而來(表示從右子樹或者虛子樹開始的一條路徑),如果當前點是合法的顏色,那麼還可以從當前點開始的一條路徑更新\(ans1\),而\(ans2\)直接全部反過來就好
void update(int x) { if (!x) return; sval[x]=sval[ch[x][0]]+sval[ch[x][1]]+val[x]; ans1[x]=min(ans1[ch[x][0]],min(fir(x),ans1[ch[x][1]])+val[x]+sval[ch[x][0]]); ans2[x]=min(ans2[ch[x][1]],min(fir(x),ans2[ch[x][0]])+val[x]+sval[ch[x][1]]); //cout<<x<<" "<<ans1[x]<<" "<<ans2[x]<<" "<<sval[x]<<endl; if (col[x]) { ans1[x]=min(ans1[x],sval[ch[x][0]]); ans2[x]=min(ans2[x],sval[ch[x][1]]); } //lmn[x]=min(lmn[ls],len[ls]+val[x]+min(w[x],fir(s[x]),lmn[rs])); //rmn[x]=min(rmn[rs],len[rs]+min(w[x],fir(s[x]),rmn[ls]+val[x])); }
其他的話,就是一些小細節了,可以直接看程式碼
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<queue> #include<cmath> #include<map> #include<set> using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();} while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x*f; } const int maxn = 5e5+1e2; //const int inf = 1e9; int lubenwei; int ch[maxn][3]; int inf; int fa[maxn],rev[maxn],ans1[maxn],ans2[maxn]; int sval[maxn],val[maxn]; int col[maxn]; int n,m; multiset<int> s[maxn]; int tot; int st[maxn]; int son(int x) { if (ch[fa[x]][0]==x) return 0; else return 1; } bool notroot(int x) { return ch[fa[x]][0]==x || ch[fa[x]][1]==x; } void reverse(int x) { swap(ans1[x],ans2[x]); rev[x]^=1; swap(ch[x][0],ch[x][1]); } int fir(int x) { //cout<<"ymh"<<endl; if (s[x].size()>=1) return *(s[x].begin()); else return inf; } void update(int x) { if (!x) return; sval[x]=sval[ch[x][0]]+sval[ch[x][1]]+val[x]; ans1[x]=min(ans1[ch[x][0]],min(fir(x),ans1[ch[x][1]])+val[x]+sval[ch[x][0]]); ans2[x]=min(ans2[ch[x][1]],min(fir(x),ans2[ch[x][0]])+val[x]+sval[ch[x][1]]); //cout<<x<<" "<<ans1[x]<<" "<<ans2[x]<<" "<<sval[x]<<endl; if (col[x]) { ans1[x]=min(ans1[x],sval[ch[x][0]]); ans2[x]=min(ans2[x],sval[ch[x][1]]); } //lmn[x]=min(lmn[ls],len[ls]+val[x]+min(w[x],fir(s[x]),lmn[rs])); //rmn[x]=min(rmn[rs],len[rs]+min(w[x],fir(s[x]),rmn[ls]+val[x])); } void pushdown(int x) { if (rev[x]) { if (ch[x][0]) reverse(ch[x][0]); if (ch[x][1]) reverse(ch[x][1]); rev[x]=0; } } void rotate(int x) { int y=fa[x],z=fa[y]; int b=son(x),c=son(y); if (notroot(y)) ch[z][c]=x; fa[x]=z; ch[y][b]=ch[x][!b]; fa[ch[x][!b]]=y; ch[x][!b]=y; fa[y]=x; update(y); update(x); } void splay(int x) { int y=x,cnt=0; st[++cnt]=y; while (notroot(y)) y=fa[y],st[++cnt]=y; while (cnt) pushdown(st[cnt--]); while (notroot(x)) { int y=fa[x],z=fa[y]; int b=son(x),c=son(y); if (notroot(y)) { if (b==c) rotate(y); else rotate(x); } rotate(x); } ///cout<<2<<endl; update(x); } void access(int x) { for (int y=0;x;y=x,x=fa[x]) { splay(x); // cout<<1; if (ch[x][1])s[x].insert(ans1[ch[x][1]]); if (y && s[x].find(ans1[y])!=s[x].end()) s[x].erase(s[x].find(ans1[y])); ch[x][1]=y; update(x); } // cout<<"wancheng"; } void makeroot(int x) { access(x);//cout<<x<<endl; splay(x); reverse(x); } int findroot(int x) { access(x); splay(x); while (ch[x][0]) { pushdown(x); x=ch[x][0]; } return x; } void split(int x,int y) { makeroot(x); access(y); splay(y); } void link(int x,int y) { split(x,y); if (findroot(y)!=x) { fa[x]=y; s[y].insert(ans1[x]); update(y); } } int main() { memset(ans1,127/3,sizeof(ans1)); memset(ans2,127/3,sizeof(ans2)); inf = ans1[maxn-3]; n=read(); lubenwei=0; tot=n; for (int i=1;i<n;i++) { int x=read(),y=read(); val[++tot]=1; link(x,tot); link(y,tot); } m=read(); makeroot(1); for (int i=1;i<=m;i++) { int opt=read(); int x=read(); if (opt==0) { makeroot(x); col[x]^=1; if (col[x]==1) lubenwei++; else lubenwei--; update(x); } if (opt==1) { makeroot(x); if (!lubenwei) cout<<-1<<"\n"; else if (col[x]) cout<<0<<"\n"; else cout<<ans1[x]<<"\n"; } // cout<<"6deyanse:"<<col[x]<<endl; } return 0; }