zoukankan      html  css  js  c++  java
  • P2056 [ZJOI2007]捉迷藏

    思路:动态点分治

    提交:3次

    错因:在加点的时候堆的操作错误。

    题解:

    为什么有时候说点分治是一种数据结构呢?我觉得是因为点分治的核心是在分治过程中产生的树形结构,即点分树,它的深度是 (log) 级别的。
    对于这道题,我们首先要建立出来点分树(只记father),每个点维护所有孩子的答案。当修改时,我们暴力跳点分树上的father(仍是 (log) 级别的)。
    如何维护信息呢?我们开三种堆:一个堆维护自己子树中的路径长度dis,就是正常点分治中的链长;再用一个堆维护每个孩子dis的堆顶,记为ch,显然,经过这个点的最长路径为堆顶和次堆顶(最大和次大);再用一个堆记录一个全局答案。
    删点时(设为 (u) ),我们先把之前的答案从全局堆中去掉,然后删掉路径长度为0的点,再尝试将答案加回全局堆。然后跳father,在堆中删掉对应的距离 (len(u,x))

    代码:

    #include<bits/stdc++.h>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    template<class I> inline I g(I& x) { x=0; register I f=1;
      register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
      do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*=f;
    } const int N=100010,M=500010,Inf=0x3f3f3f3f;
    int n,m,cnt,sum,rt; bool vis[N];
    int vr[N<<1],nxt[N<<1],fir[N],sz[N],mx[N],d[N],c[N],fa[N],len[20][N];
    inline void add(int u,int v) {
      vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;
      vr[++cnt]=u,nxt[cnt]=fir[v],fir[v]=cnt;
    }
    struct heap {
      priority_queue<int> dat,dst;
      inline void ins(int x) {dat.push(x);}
      inline void del(int x) {dst.push(x);}
      inline int top() {
        while(dst.size()&&dat.top()==dst.top()) dat.pop(),dst.pop();
        return dat.top();
      }
      inline void pop() {
        while(dst.size()&&dat.top()==dst.top()) dat.pop(),dst.pop(); dat.pop();
      }
      inline int rtop() {
        R t=top(),ret; pop();
        ret=top(); dat.push(t); return ret;
      }
      inline int size() {return dat.size()-dst.size();}
    }dis[N],ch[N],ans;
    inline void getsz(int u,int fa) {
      sz[u]=1,mx[u]=0; 
      for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
        if(v==fa||vis[v]) continue;
        getsz(v,u),sz[u]+=sz[v];
        mx[u]=max(mx[u],sz[v]); 
      } mx[u]=max(mx[u],sum-sz[u]);
      if(mx[u]<mx[rt]) rt=u;
    }
    inline void dfs(int u,int fa,int s,heap& q) {
      q.ins(s); for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
        if(v==fa||vis[v]) continue; dfs(v,u,s+1,q);
      }
    }
    inline void pre(int u) { vis[u]=true;
      for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
        if(vis[v]) continue;
        sum=sz[v],rt=0,mx[0]=Inf;
        getsz(v,-1),getsz(rt,-1); fa[rt]=u; 
        dfs(v,-1,1,dis[rt]); ch[u].ins(dis[rt].top());
        d[rt]=d[u]+1; pre(rt);
      } ch[u].ins(0); if(ch[u].size()>=2) ans.ins(ch[u].top()+ch[u].rtop());
      else if(ch[u].size()) ans.ins(ch[u].top());
    }
    namespace lca {
    int d[N],lg[N],f[20][N];
    inline void dfs(int u,int fa) {
      for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
        if(v==fa) continue;
        d[v]=d[u]+1; f[0][v]=u; dfs(v,u);
      }
    }
    inline void init() {
      dfs(1,-1); for(R i=2;i<=n;++i) lg[i]=lg[i>>1]+1;
      for(R i=1;i<=lg[n];++i) for(R j=1;j<=n;++j)
        f[i][j]=f[i-1][f[i-1][j]];
    }
    inline int query(int u,int v) { if(d[u]<d[v]) swap(u,v); 
      for(R k=lg[d[u]];~k;--k) if(d[f[k][u]]>=d[v]) u=f[k][u];
      if(u==v) return u; 
      for(R k=lg[d[u]];~k;--k) if(f[k][u]!=f[k][v]) u=f[k][u],v=f[k][v];
      return f[0][u];
    }
    inline int dis(int u,int v) {return d[u]+d[v]-2*d[query(u,v)];}
    }
    inline void main() {
      g(n); for(R i=1,u,v;i<n;++i) g(u),g(v),add(u,v);
      lca::init(); rt=0; mx[rt]=Inf; sum=n; getsz(1,-1),getsz(rt,-1),pre(rt);
      for(R u=1;u<=n;++u) for(R i=u;i;i=fa[i]) len[d[u]-d[i]][u]=lca::dis(u,i);
      g(m); while(m--) { register char s[2]; scanf("%s",s);
        if(s[0]=='G') if(ans.size()) printf("%d
    ",ans.top()); else puts("-1");
        else { R u; g(u); 
          if(!c[u]) {
            if(ch[u].size()>=2) ans.del(ch[u].top()+ch[u].rtop());
            ch[u].del(0); if(ch[u].size()>=2) ans.ins(ch[u].top()+ch[u].rtop());
            for(R i=u;fa[i];i=fa[i]) {
              if(ch[fa[i]].size()>=2) ans.del(ch[fa[i]].top()+ch[fa[i]].rtop());
              ch[fa[i]].del(dis[i].top());
              dis[i].del(len[d[u]-d[fa[i]]][u]);
              if(dis[i].size()) ch[fa[i]].ins(dis[i].top());
              if(ch[fa[i]].size()>=2) ans.ins(ch[fa[i]].top()+ch[fa[i]].rtop());
            }
          } else {
            if(ch[u].size()>=2) ans.del(ch[u].top()+ch[u].rtop());
            ch[u].ins(0); if(ch[u].size()>=2) ans.ins(ch[u].top()+ch[u].rtop());
            for(R i=u;fa[i];i=fa[i]) {
              if(ch[fa[i]].size()>=2) ans.del(ch[fa[i]].top()+ch[fa[i]].rtop());
              if(dis[i].size()) ch[fa[i]].del(dis[i].top());
              dis[i].ins(len[d[u]-d[fa[i]]][u]);
              ch[fa[i]].ins(dis[i].top());
              if(ch[fa[i]].size()>=2) ans.ins(ch[fa[i]].top()+ch[fa[i]].rtop());
            }
          } c[u]^=1;
        }
      } 
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    2019.08.31
    69

  • 相关阅读:
    poj2478
    poj2376
    poj2192
    poj1062
    [HDOJ2639]Bone Collector II(第k优01背包)
    [HDOJ3466]Proud Merchants(贪心+01背包)
    [HDOJ5510]Bazinga(并查集)
    [POJ3264]Balanced Lineup(线段树,区间最值差)
    [HDOJ4325]Flowers(树状数组 离散化)
    [HDOJ5521]Meeting(最短路)
  • 原文地址:https://www.cnblogs.com/Jackpei/p/11437901.html
Copyright © 2011-2022 走看看