zoukankan      html  css  js  c++  java
  • 平衡树性质+思维——NWERC 2019 Balanced Cut

    找了老半天错误。。

    高度为i的平衡树至少要有f(i)=f(i-1)+f(i-2)+1个结点
    从小到达枚举i,如果i被选中,那么其所有祖先p也必被选中
    考虑i能否加入:如果i在祖先p的左子树里,p的左子树高度更新,连带更新右子树必须要有的高度
    如果i在组先p的右子树里,更新右子树高度,只要右子树高度<=左子树高度+1即可

    /*
    高度为i的平衡树至少要有f(i)=f(i-1)+f(i-2)+1个结点
    从小到达枚举i,如果i被选中,那么其所有祖先p也必被选中
    考虑i能否加入:如果i在祖先p的左子树里,p的左子树高度更新,连带更新右子树必须要有的高度
              如果i在组先p的右子树里,更新右子树高度,只要右子树高度<=左子树高度+1即可 
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define N 600005
    
    int ans[N],k,n,mi[N],ls[N],rs[N],fa[N],dl[N],d[N];
    
    void dfs(int u){
        if(ls[u]){
            d[ls[u]]=d[u]+1;
            dfs(ls[u]);
        }
        if(rs[u]){
            d[rs[u]]=d[u]+1;
            dfs(rs[u]);
        }
    }
    
    int main(){
        mi[1]=1;mi[2]=2;
        for(int i=3;i<=3000;i++)
            mi[i]=mi[i-1]+mi[i-2]+1;
        cin>>n>>k;
        for(int i=1;i<=n;i++){
            cin>>fa[i];
            if(fa[i]!=-1){
                if(i<fa[i])ls[fa[i]]=i;
                else rs[fa[i]]=i;
            }
        }
        
        int root;
        for(int i=1;i<=n;i++)if(fa[i]==-1)root=i;
        dfs(root);
        
        for(int i=1;i<=n;i++)if(!ans[i]){
            int pre=fa[i],now=i,tot=k;
            while(pre!=-1){
                if(!ans[pre])tot--;//祖先没被选过 
                if(now==ls[pre]){//now是pre左子树 
                    int t=d[i]-d[pre];
                    if(dl[pre]<t)
                        tot-=mi[t-1]; 
                    else tot-=mi[dl[pre]-1];
                }else{//now是pre右子树 
                    if(!ans[pre]){tot=-1;break;}
                    int t=d[i]-d[pre];
                    if(t>dl[pre]+1){tot=-1;break;} 
                }
                now=pre;pre=fa[now];
            }
            if(tot>=1){
                ans[i]=1;k--;
                int pre=fa[i],now=i;
                while(pre!=-1){
                    if(!ans[pre])ans[pre]=1,k--;
                    if(now==ls[pre]){
                        int t=d[i]-d[pre];
                        if(dl[pre]<t){
                            dl[pre]=t;
                        }
                    }
                    now=pre;pre=fa[pre];
                }
            }else {
                ans[i]=0;
            }
        }
        
        for(int i=1;i<=n;i++)cout<<ans[i];
        
    } 
    View Code

    标程好像用的是另一种方法。。

    #include <cstdio>
    #include <algorithm>
    using namespace std;
     
    int p,l,pi[233],pf[555555],pp[555555][2],dd[555555],pd[555555],pl[555555];
    bool ff[555555];
     
    void shu(int k,int d)
    {
        if(k==0) return;
        dd[k]=d;
        shu(pp[k][0],d+1);
        shu(pp[k][1],d+1);
        pl[k]=max(pl[pp[k][0]],pl[pp[k][1]])+1;
        return;
    }
     
    void tui(int k,int d)
    {
        if(k==0||d<=0) return;
        pd[k]=d; ff[k]=true;
        if(pl[pp[k][0]]>=d-1)
        {
            tui(pp[k][0],d-1);
            if(d-2>0) tui(pp[k][1],d-2);
        }
        else
        {
            tui(pp[k][1],d-1);
            if(d-2>0) tui(pp[k][0],d-2);
        }
        return;
    }
     
    bool shang(int k,int d,int &p)
    {
        if(pf[k]==-1) return true;
        int t=p;
        if(k<pf[k])
        {
            if(ff[pf[k]]==false)
            {
                if(t==0) return false;
                t--;
            }
            if(pd[pp[pf[k]][1]]<d-2)
            {
                t-=pi[d-2]-pi[pd[pp[pf[k]][1]]];
                if(t<0) return false;
            }
            if(shang(pf[k],d+1,t))
            {
                ff[pf[k]]=true; p=t;
                pd[pf[k]]=max(pd[pf[k]],d);
                pd[pp[pf[k]][1]]=max(pd[pp[pf[k]][1]],d-2);
                return true;
            }
        }
        else
        {
            if(ff[pf[k]]==false||d-pd[pp[pf[k]][0]]>2) return false;
            if(shang(pf[k],d+1,t))
            {
                p=t;
                pd[pf[k]]=max(pd[pf[k]],d);
                return true;
            }
        }
        return false;
    }
     
    int main()
    {
        pi[1]=1; pi[2]=2;
        for(int i=3; i<233; i++)
        {
            pi[i]=pi[i-1]+pi[i-2]+1;
            if(pi[i]>500000) break;
        }
        int n,root; scanf("%d%d",&n,&p);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&pf[i]);
            if(pf[i]==-1) root=i;
            else if(i<pf[i]) pp[pf[i]][0]=i;
            else pp[pf[i]][1]=i;
        }
        shu(root,1);
        for(int i=1; i<=n; i++)
        {
            if(ff[i]==true)
            {
                if(pd[pp[i][1]]>0) tui(pp[i][1],pd[pp[i][1]]);
                continue;
            }
            if(p==0) continue;
            int t=p-1;
            if(shang(i,2,t))
            {
                ff[i]=true; p=t;
                pd[i]=max(pd[i],1);
            }
        }
        for(int i=1; i<=n; i++) if(ff[i]==true)
            printf("1");
        else
            printf("0");
        return 0;
    }
  • 相关阅读:
    一个iOS程序员眼中的跨域问题
    web 大规模并发访问的解决方案
    修改Capfile,在正式环境不再使用migration修改数据库
    关于 CAS 不能登录的问题
    老项目占地比较大的原因是release文件夹里有.git 目录
    capistrano3.4.0部署不能自动登录
    capistrano/blob/v3.4.0部署
    私有方法的查找方式
    开启关闭功能没有生效的原因
    找不到Settings
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12887984.html
Copyright © 2011-2022 走看看