zoukankan      html  css  js  c++  java
  • BZOJ4855 : [Jsoi2016]轻重路径

    首先用树状数组维护dfs序来快速支持一个点子树大小的询问。

    每次删掉一个叶子时,从根开始往叶子走,显然只有$2size[x]leq size[father]$的点的父亲才有可能换重儿子。

    从根开始往下,找到最高的满足条件的点,从那个点开始继续迭代,每次点数至少减小一半,所以迭代只有$O(log n)$次。

    时间复杂度$O(nlog^2n)$。

    #include<cstdio>
    const int N=200010;
    int n,m,x,i,ch[N][2],size[N],f[N],d[N],son[N],top[N],st[N],en[N],q[N],dfn,bit[N];long long ans;
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    inline void add(int x,int p){for(;x<=n;x+=x&-x)bit[x]+=p;}
    inline int ask(int x){int t=0;for(;x;x-=x&-x)t+=bit[x];return t;}
    inline int getsize(int x){
      if(!x)return 0;
      return ask(en[x])-ask(st[x]-1);
    }
    void dfs(int x){
      size[x]=1;
      for(int i=0;i<2;i++){
        int y=ch[x][i];
        if(!y)continue;
        f[y]=x;d[y]=d[x]+1;
        dfs(y),size[x]+=size[y];
        if(size[y]>size[son[x]])son[x]=y;
      }
      ans+=son[x];
    }
    void dfs2(int x,int y){
      q[st[x]=++dfn]=x;top[x]=y;
      if(son[x])dfs2(son[x],y);
      for(int i=0;i<2;i++){
        int o=ch[x][i];
        if(!o||o==son[x])continue;
        dfs2(o,o);
      }
      en[x]=dfn;
    }
    inline int up(int x,int k){
      while(1){
        if(st[x]-st[top[x]]>=k)return q[st[x]-k];
        k-=st[x]-st[top[x]]+1;
        x=f[top[x]];
      }
    }
    inline void recal(int x){
      if(!x)return;
      ans-=son[x];
      int t=0;
      for(int i=0;i<2;i++){
        int y=ch[x][i],w=getsize(y);
        if(w>t)t=w;
      }
      if(!t)son[x]=0;
      else if(getsize(son[x])!=t){
        if(getsize(ch[x][0])==t)son[x]=ch[x][0];
        else son[x]=ch[x][1];
      }
      ans+=son[x];
    }
    inline void remove(int x){
      add(st[x],-1);
      int lim=d[x],o=lim;
      while(1){
        int l=1,r=o,mid,t=0,s=getsize(up(x,o));
        while(l<=r)if(getsize(up(x,mid=(l+r)>>1))*2<=s)l=(t=mid)+1;else r=mid-1;
        recal(f[up(x,t)]);
        if(!o)return;
        o=t;
      }
    }
    int main(){
      while(~scanf("%d",&n)){
        if(!n)return 0;
        for(dfn=ans=0,i=1;i<=n;i++)size[i]=son[i]=bit[i]=0;
        for(i=1;i<=n;i++)read(ch[i][0]),read(ch[i][1]);
        dfs(1);
        dfs2(1,1);
        printf("%lld
    ",ans);
        for(i=1;i<=n;i++)add(i,1);
        for(read(m);m--;printf("%lld
    ",ans))read(x),remove(x);
      }
      return 0;
    }
    

      

  • 相关阅读:
    MySQL 数据恢复
    由 go orm 引发的探索
    beego 优雅重启
    2020年8月20日
    Linux 递归获取目录下所有满足条件的文件
    NET Core Kestrel部署HTTPS 一个服务器绑一个证书 一个服务器绑多个证书
    Flutter环境配置-windows
    Vue获取钉钉免登陆授权码(vue中的回调函数实践)
    【C#上位机必看】你们要的Iot物联网项目来了
    Windows Server系统部署MySQL数据库
  • 原文地址:https://www.cnblogs.com/clrs97/p/6769345.html
Copyright © 2011-2022 走看看