zoukankan      html  css  js  c++  java
  • 洛谷P5773 [JSOI2016] 轻重路径

    一次删点只会影响该点到根节点路径上的点,若路径上的点 (x) 在删点后满足 (size_x leqslant frac{1}{2}size_{root}) 则点 (x) 的父边会从重边变为轻边,二分找到满足条件的深度最浅的点,调整其重儿子的关系后,将其设为接下来考虑的根节点,然后继续二分找满足条件的点。

    因为一个点到根节点的轻边个数为 (O(log n)),所以二分进行的轮数也为 (O(log n))。用树状数组维护 (size) 变化即可。

    #include<bits/stdc++.h>
    #define maxn 400010
    #define lowbit(x) (x&(-x))
    using namespace std;
    typedef long long ll;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    int n,q,cnt;
    ll ans;
    int fa[maxn],ch[maxn][2],siz[maxn],son[maxn],dep[maxn],f[maxn][19],in[maxn],out[maxn],rev[maxn],t[maxn];
    void update(int x,int v)
    {
        while(x<=n) t[x]+=v,x+=lowbit(x);
    }
    int ask(int x)
    {
        int v=0;
        while(x) v+=t[x],x-=lowbit(x);
        return v;
    }
    int query(int x)
    {
    	if(!x) return 0;
        return ask(out[x])-ask(in[x]-1);
    }
    void dfs(int x)
    {
        if(!x) return;
        siz[x]=1,rev[in[x]=++cnt]=x,dep[x]=dep[f[x][0]=fa[x]]+1;
        for(int i=1;i<=17;++i) f[x][i]=f[f[x][i-1]][i-1];
        for(int i=0;i<=1;++i) dfs(ch[x][i]),siz[x]+=siz[ch[x][i]];
        out[x]=cnt,ans+=son[x]=(siz[ch[x][0]]>=siz[ch[x][1]]?ch[x][0]:ch[x][1]);
    }
    int get(int x,int k)
    {
        for(int i=0;i<=17;++i)
            if((k>>i)&1)
                x=f[x][i];
        return x;
    }
    int main()
    {
        read(n);
        for(int i=1;i<=n;++i)
        {
        	update(i,1);
    		for(int j=0;j<=1;++j)
                read(ch[i][j]),fa[ch[i][j]]=i;
        }
        dfs(1),printf("%lld
    ",ans),read(q);
        while(q--)
        {
            int p,rt=1;
            read(p),update(in[p],-1);
            while(true)
            {
                int l=0,r=dep[p]-dep[rt]-1,d=-1,s=query(rt);
                while(l<=r)
                {
                    int mid=(l+r)>>1;
                    if(query(get(p,mid))<=s/2) d=mid,l=mid+1;
                    else r=mid-1;
                }
                if(d!=-1)
                {
                    int x=get(p,d),y=ch[fa[x]][(ch[fa[x]][1]==x)^1],sx=query(x),sy=query(y);
                    if(son[fa[x]]==x)
                    {
                        if(sx+1==sy) ans+=y-x,son[fa[x]]=y;
                        else if(!sx&&!sy) ans-=x,son[fa[x]]=0;
                    }
                    rt=x;
                }
                else break;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    js 作用域
    js 实现二级联动
    JavaScript 基础(四)
    JavaScript 基础(三)
    数据库事务的基本概念
    二进制安装 kubernetes 1.12(五)
    二进制安装 kubernetes 1.12(四)
    二进制安装 kubernetes 1.12(三)
    二进制安装 kubernetes 1.12(二)
    Centos 7.x 安装 Docker-ce
  • 原文地址:https://www.cnblogs.com/lhm-/p/14032830.html
Copyright © 2011-2022 走看看