• 解题:九省联考2018 IIIDX


    题面

    我当时在考场上划水的时候好像乱搞搞了20pts,然后发现一堆同届的都写了55pts的贪心=。=???

    那就先说那55pts的贪心吧,这个现在看起来还是非常显然的,就是按题意来每一块是分属一个点的,其实这就是棵树,排序之后从叶子往上递增地放就可以了,挺送的=。=

    为什么错了,显然有相同的数的时候可能把一个大点的数放前面也是对的,然后就不优了。如何抢救这个算法哪?

    我们继续刚才那个思路,那么一个数可以填到当前的位置上当且仅当大于等于它的数的数目大于等于这个数所在子树的大小。我们先预留出一个点的子树那些数,然后线段树护维护对于每个位置

    还能填的数的个数。每次在线段树上二分出最小的(有好几个一样的就找最靠右的)大于等于子树预留大小的位置填上去,之后更新小于这个数的位置的能填的数的个数。

    注意每次查询时如果父亲还给这个节点预留着位置先把位置放下来,填完再把这个点的子树留回去

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=500005,M=2e6+20;
     6 int val[N],fth[N],siz[N],lst[N];
     7 int n,minn[M],laz[M],rnk[N]; 
     8 double k;
     9 bool cmp(int x,int y)
    10 {
    11     return x>y;
    12 }
    13 void Release(int nde)
    14 {
    15     if(laz[nde])
    16     {
    17         int ls=2*nde,rs=2*nde+1;
    18         minn[ls]+=laz[nde],minn[rs]+=laz[nde];
    19         laz[ls]+=laz[nde],laz[rs]+=laz[nde],laz[nde]=0;
    20     }
    21 }
    22 void Create(int nde,int l,int r)
    23 {
    24     if(l==r)
    25         minn[nde]=l;
    26     else
    27     {
    28         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
    29         Create(ls,l,mid),Create(rs,mid+1,r);
    30         minn[nde]=min(minn[ls],minn[rs]);
    31     }
    32 }
    33 void Change(int nde,int l,int r,int ll,int rr,int tsk)
    34 {
    35     if(l>rr||r<ll)
    36         return ;
    37     else if(l>=ll&&r<=rr)
    38         minn[nde]+=tsk,laz[nde]+=tsk;
    39     else
    40     {
    41         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; Release(nde);
    42         Change(ls,l,mid,ll,rr,tsk),Change(rs,mid+1,r,ll,rr,tsk);
    43         minn[nde]=min(minn[ls],minn[rs]);
    44     }
    45 }
    46 int Query(int nde,int l,int r,int tsk)
    47 {
    48     if(l==r)
    49         return l+(tsk>minn[nde]);
    50     else
    51     {
    52         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; Release(nde);
    53         return (tsk<=minn[rs])?Query(ls,l,mid,tsk):Query(rs,mid+1,r,tsk);
    54     }
    55 }
    56 int main()
    57 {
    58     scanf("%d%lf",&n,&k);
    59     for(int i=1;i<=n;i++)
    60         scanf("%d",&val[i]),siz[i]=1;
    61     sort(val+1,val+1+n,cmp);
    62     for(int i=n;i;i--)
    63     {
    64         fth[i]=1.0*i/k,siz[fth[i]]+=siz[i];
    65         if(val[i]==val[i+1]) lst[i]=lst[i+1]+1;
    66     }
    67     Create(1,1,n);
    68     for(int i=1;i<=n;i++)
    69     {
    70         if(fth[i]!=fth[i-1]) 
    71             Change(1,1,n,rnk[fth[i]],n,siz[fth[i]]-1);
    72         int ans=Query(1,1,n,siz[i]);
    73         ans+=lst[ans],lst[ans]++,ans-=lst[ans]-1;
    74         rnk[i]=ans,Change(1,1,n,ans,n,-siz[i]);
    75     }
    76     for(int i=1;i<=n;i++)
    77         printf("%d ",val[rnk[i]]);
    78     return 0;
    79 }
    View Code
  • 相关阅读:
    开发安全测试工具 ,推荐6款完全免费的工具
    Asp.net MVC 出现IQueryable<T> 未包含“Include”的定义
    Windows系统Git安装教程(详解Git安装过程)
    窗体进行自动适应窗口
    C# ObservableCollection两个字段排序的情况
    Advanced Installer 14.9 – WPF或winform应用程序打包成exe文件
    DotNetCore部署(IIS)踩坑记
    DotNetCore部署(IIS)文档
    windows系统中Dotnet core runtime 安装后,无法启动次程序,因为计算机中丢失api-ms-win-crt-runtime-l1-1-0.dll的解决方法
    解决Git在添加ignore文件之前就提交了项目无法再过滤问题
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10279005.html
Copyright © 2020-2023  润新知