题意:给定一棵树,每个节点可以变成黑白两色。一开始所有节点都是黑色,操作可将点颜色改变,询问当前情况下距离最远的两个黑点的距离。

动态树分治。一开始想的是对于每个节点维护主大和次大,后来发现这实在是太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 }