zoukankan      html  css  js  c++  java
  • 解题:九省联考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
  • 相关阅读:
    VueRouter-编程式导航
    VueRouter-路由嵌套
    ubuntu安装qt时编译出现cstddef:50:10: fatal error: 'stddef.h' file not found
    六种常用位操作运算符原理及用途
    C语言编写程序的大小端问题
    linux系统中运行node进程,无法杀死进程
    满足客户的特殊需求,特殊轮播图非常规轮播图
    什么?你还不会通过纯js提交表单?
    什么?你还不会身份证号码验证?最全的身份证正则验证js
    什么!你想要封装好的ajax
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10279005.html
Copyright © 2011-2022 走看看