题意:给定一棵树,每个节点可以变成黑白两色。一开始所有节点都是黑色,操作可将点颜色改变,询问当前情况下距离最远的两个黑点的距离。
动态树分治。一开始想的是对于每个节点维护主大和次大,后来发现这实在是太NAIVE了。实际上,正解是这样的:
对于每个点,维护两个堆(接下来说的都是点分树上的节点):第一个堆,该点子树到该点父亲的距离,第二个堆,该点直接儿子的第一个堆的堆顶元素。
然后我们再开一个全局堆,即答案堆,维护所有第二个堆最大和次大之和。每次询问只要把堆顶元素拿出来就可以了。
为什么空间开的下呢?这个道理和震波那道题是一样的,考虑点分治的时间复杂度,每个点最大堆空间开到的就是该点子树大小,总和是nlogn的,完全开的下。
怎么修改呢,暴力爬树高啊,点分树不就是这一点树高稳定log最好吗!
维护3个堆的过程特别繁琐,写的时候写了一个上午。。。就为了那几个if。。
最后被自己模拟的堆坑了一发。。改到现在才过
上代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 #define INF 1e9 5 inline int read(){ 6 int x=0,f=1; char a=getchar(); 7 while(a<'0' || a>'9') {if(a=='0') f=-1; a=getchar();} 8 while(a>='0' && a<='9') x=x*10+a-'0',a=getchar(); 9 return x*f; 10 } 11 int n,q,head[N],s[N],cnt,f[N],rt,sz,dep[N],fa[N][20],dis[N][20],now; 12 char ch[2]; bool vis[N],on[N]; 13 struct heap{ 14 priority_queue<int>A,B; 15 void push(int x) {A.push(x);} 16 void erase(int x) {B.push(x);} 17 void pop() {while(B.size()&&A.top()==B.top()) A.pop(),B.pop(); A.pop();} 18 int top() {while(B.size()&&A.top()==B.top()) A.pop(),B.pop(); if(A.size()) return A.top(); else return -INF;} 19 int size() {return A.size()-B.size();} 20 int s_top(){ if(size()<2) return -INF; 21 while(B.size()&&A.top()==B.top()) A.pop(),B.pop(); 22 int t=A.top(),ret; A.pop(); 23 while(B.size()&&A.top()==B.top()) A.pop(),B.pop(); 24 ret=A.top(); A.push(t); 25 return ret; 26 } 27 }C,A[N],B[N]; 28 struct edges{ 29 int to,next; 30 }e[2*N]; 31 void insert(){ 32 int u=read(),v=read(); 33 e[cnt]=(edges){v,head[u]};head[u]=cnt++; 34 e[cnt]=(edges){u,head[v]};head[v]=cnt++; 35 } 36 void getroot(int x,int p){ 37 s[x]=1; f[x]=0; 38 for(int i=head[x];i>=0;i=e[i].next){ 39 if(vis[e[i].to] || p==e[i].to) continue; 40 getroot(e[i].to,x); s[x]+=s[e[i].to]; 41 f[x]=max(f[x],s[e[i].to]); 42 } 43 f[x]=max(f[x],sz-s[x]); 44 if(f[rt]>f[x]) rt=x; 45 } 46 void getship(int x,int anc,int p,int d){ 47 for(int v,i=head[x];i>=0;i=e[i].next){ 48 v=e[i].to; 49 if(vis[v] || p==v) continue; 50 fa[v][++dep[v]]=anc; dis[v][dep[v]]=d; getship(v,anc,x,d+1); 51 } 52 } 53 void buildtree(int x){ 54 vis[x]=1; getship(x,x,0,1); int all=sz; 55 for(int i=head[x];i>=0;i=e[i].next){ 56 if(vis[e[i].to]) continue; 57 if(s[e[i].to]>s[x]) s[e[i].to]=all-s[x]; sz=s[e[i].to]; 58 rt=0; getroot(e[i].to,x); buildtree(rt); 59 } 60 } 61 void turn_off(int x){ 62 B[x].push(0); 63 if(B[x].size()==2) C.push(B[x].top()); 64 for(int t,pre,i=dep[x];i>1;i--){ 65 if(!A[fa[x][i]].size()){ 66 A[fa[x][i]].push(dis[x][i-1]); 67 pre=B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top(); 68 B[fa[x][i-1]].push(dis[x][i-1]); 69 if(pre>0 && pre==B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top()) continue; 70 if(pre>0 && pre!=B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top()) 71 C.erase(pre),C.push(B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top()); 72 else if(B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top()>0) C.push(B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top()); 73 }else{ 74 t=A[fa[x][i]].top(); A[fa[x][i]].push(dis[x][i-1]); 75 if(t<dis[x][i-1]){ 76 pre=B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top(); 77 B[fa[x][i-1]].erase(t); B[fa[x][i-1]].push(dis[x][i-1]); 78 if(pre>0 && pre!=B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top()) 79 C.erase(pre),C.push(B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top()); 80 } 81 } 82 } 83 } 84 void turn_on(int x){ 85 B[x].erase(0); 86 if(B[x].size()==1) C.erase(B[x].top()); 87 for(int t,pre,i=dep[x];i>1;i--){ 88 A[fa[x][i]].erase(dis[x][i-1]); 89 if(A[fa[x][i]].top()<dis[x][i-1]) { 90 pre=B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top(); 91 B[fa[x][i-1]].erase(dis[x][i-1]); 92 if(A[fa[x][i]].size()) B[fa[x][i-1]].push(A[fa[x][i]].top()); 93 if(pre>0) { 94 if(pre==B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top()) continue; 95 C.erase(pre); 96 if(B[fa[x][i-1]].size()>1) 97 C.push(B[fa[x][i-1]].top()+B[fa[x][i-1]].s_top()); 98 } 99 } 100 } 101 } 102 inline void change(int x){ 103 if(!on[x]) turn_on(x); 104 else turn_off(x); 105 on[x]^=1; 106 if(on[x]) now++; 107 else now--; 108 } 109 int main(){ 110 n=read(); memset(head,-1,sizeof(head)); 111 for(int i=1;i<n;i++) insert(); 112 f[0]=INF; sz=n; getroot(1,0); buildtree(rt); 113 for(int i=1;i<=n;i++) fa[i][++dep[i]]=i,turn_off(i); 114 q=read(); 115 while(q--){ 116 scanf("%s",ch); 117 if(ch[0]=='G') { 118 if(now==n) puts("-1"); 119 else printf("%d\n",max(C.top(),0)); 120 } 121 else change(read()); 122 } 123 return 0; 124 }