zjoi 2007 捉迷藏 动态点分治+可删堆

https://www.luogu.org/problem/P2056

题解:来自https://blog.csdn.net/ccsu_cat/article/details/101036382

 这代码是真的长,一码就是150行+

特殊之处在于这个题需要维护一个可删堆

#include<bits/stdc++.h>
#define ll long long
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define ull unsigned long long
#define fi first
#define se second
#define mp make_pair
#define pii pair<ll,ll>
using namespace std;//head
const int maxn=4e5+10,maxm=2e6+10;
const ll INF=0x3f3f3f3f,mod=1e9+7;
int casn,n,m,k;
namespace graph{
  vector<int>g[maxn];
  bool vis[maxn];
  int all,sz[maxn],root,maxt,father[maxn];
  int _deep[maxn],_dfn[maxn],_cnt;
  int son[maxn];
  int _lca[maxn][int(log(maxn)/log(2))+1];
  int logn[maxn];
  void add(int a,int b){
    g[a].emplace_back(b);g[b].emplace_back(a);
  }
  int dfs_root(int now,int fa){
    int cnt=1;
    son[now]=0;
    for(auto to:g[now])if(to!=fa&&!vis[to]){
      int ch=dfs_root(to,now);
      son[now]=max(son[now],ch);
      cnt+=ch;
    }
    son[now]=max(son[now],all-cnt);
    if(son[now]<son[root]) root=now;
    return sz[now]=cnt;
  }
  void dfs_lca(int now,int fa){
    _dfn[now]=++_cnt;
    _lca[_cnt][0]=_deep[now]=_deep[fa]+1;
    for(auto to:g[now]) {
      if(to==fa) continue;
      dfs_lca(to,now);
      _lca[++_cnt][0]=_deep[now];
    }
  }
  class node{public:
    priority_queue<int> x,y;
    inline void push(int a){x.push(a);}
    inline void remove(int a){y.push(a);}
    inline int top(){
      while(y.size()&&x.top()==y.top())
      x.pop(),y.pop();return x.top();
    }
    inline int size(){return x.size()-y.size();}
    inline void pop(){
      while(y.size()&&x.top()==y.top())
      x.pop(),y.pop();
      x.pop();
    }
    inline int sectop(){int a=top();pop();int b=top();push(a);return b;}
  }ans0,b[maxn],c[maxn];
  void cal_st(){
    logn[0]=-1;
    rep(i,1,2e5+10) logn[i]=logn[i>>1]+1;
    rep(j,1,logn[_cnt])rep(i,1,_cnt-(1<<j)+1)
      _lca[i][j]=min(_lca[i][j-1],_lca[i+(1<<(j-1))][j-1]);
  }
  int _dis(int a,int b){
    a=_dfn[a],b=_dfn[b];
    if(a>b) swap(a,b);
    int len=logn[b-a+1];
    return min(_lca[a][len],_lca[b-(1<<len)+1][len]);
  }
  int dis(int a,int b){
    int res=_deep[a]+_deep[b]-2*_dis(a,b);
    return res;
  }
  void dfs_cal(int now,int fa){
    c[root].push(dis(now,father[root]));
    for(auto to:g[now]){
      if(to==fa||vis[to]) continue;
      dfs_cal(to,now);
    }
  }
  void pusha(int now){
    if(b[now].size()>=2) 
      ans0.push(b[now].top()+b[now].sectop());
  }
  void dela(int now){
    if(b[now].size()>=2) 
      ans0.remove(b[now].top()+b[now].sectop());
  }
  void dfs_dv(int now,int fa){
    father[now]=fa;vis[now]=1;
    b[now].push(0);
    dfs_cal(now,0);
    for(auto to:g[now]){
      if(vis[to]) continue;
      all=sz[to],root=0;
      dfs_root(to,0);
      int tmp=root;
      dfs_dv(root,now);
      b[now].push(c[tmp].top());
    }
    pusha(now);
  }
  void on(int pos){
    dela(pos);
    b[pos].remove(0);
    pusha(pos);
    for(int now=pos;father[now];now=father[now]){
      dela(father[now]);
      b[father[now]].remove(c[now].top());
      c[now].remove(dis(pos,father[now]));
      if(c[now].size()) b[father[now]].push(c[now].top());
      pusha(father[now]);
    }
  }
  void off(int pos){
    dela(pos);
    b[pos].push(0);
    pusha(pos);
    for(int now=pos;father[now];now=father[now]){
      dela(father[now]);
      if(c[now].size()) b[father[now]].remove(c[now].top());
      c[now].push(dis(pos,father[now]));
      b[father[now]].push(c[now].top());
      pusha(father[now]);
    }
  }
  void init(int n){
    _cnt=0;
    dfs_lca(1,0);
    cal_st();
    son[0]=n;
    all=n;root=0;
    dfs_root(1,0);
    dfs_dv(root,0);
  }
}
using namespace graph;
bool sw[maxn];
int main() {IO;
  int a,b;
  rep(i,1,maxn-5) logn[i]=logn[i>>1]+1;
  cin>>n;
  rep(i,2,n){
    cin>>a>>b;
    add(a,b);
  }
  init(n);
  int cnt=n;
  cin>>m;
  while(m--){
    string s;cin>>s;
    if(s[0]=='G'){
      if(cnt<=1) cout<<cnt-1<<endl;
      else cout<<ans0.top()<<endl;
    }else {
      int pos;cin>>pos;
      if(!sw[pos]) on(pos),--cnt;
      else off(pos),++cnt;
      sw[pos]^=1;
    }
  }
}
原文地址:https://www.cnblogs.com/nervendnig/p/11630122.html