codeforces D. Cutting Out +二分

题目链接:http://codeforces.com/contest/1077/problem/D
题目大意:

给你n个的整数的主序列,要求你在主序列中找k个的整数。
然后在主序列中删除这k个数字,如果主序列还有这k个整数,可以继续删除。

输出能使删除次数最多的k的数字。

样例1, 2, 3的数字都在主串中出现了2次。所以输出次数为2。已经是最大的。

思路:开始用了贪心。统计了所有的数字出现次数。在拿出前k个

while(如果其中最小的次数*2<最大的次数)
{
删除最小的次数。最大的次数。
添加最大的次数/2, 最大的次数-(最大的次数/2)。
}
一直WA4,现在贪心发现了问题。例如:
9 3 1 1
第一次循环
5 4 3 1
第二次循环
4 3 2 3
那么最大的次数是2

实际上可以分成3 3 3 3
那么最大的次数是3

贪心显然不能做,不过这个复杂度至少要nlogn才能过,所以可以考虑二分,把删除的次数二分l=1; r=n;

思考:复杂度为nlogn时除了STL还可以考虑二分,自己往往一直用STL。下次还是要多考虑一下二分。

#include<bits/stdc++.h>
using namespace std;

int a[200005];

int pd(int mid, int k)
{
    int m=mid, key=0;
    for(int i=0;i<200005;i++)
    {
         if(a[i]>=m)
            key+=a[i]/m;

         if(key>=k)
            return 1;
    }
    return 0;
}

int main()
{
    fill(a, a+200005, 0);
    int n, k;
    scanf("%d%d",&n,&k);
    for(int i=0;i<n;i++)
    {
        int t;
        scanf("%d",&t);
        a[t]++;
    }
    int l=1;
    int r=n;
    int w=0;

    while(l<=r)//二分
    {
        int mid=(l+r)/2;
        int p=pd(mid, k);
        if(p)
            l=mid+1, w=mid;
        else
            r=mid-1;

    }
    
    for(int i=0;i<200005;i++)//按照删除次数找元素输出
    {
         if(a[i]>=w)
         {
             int t=a[i]/w;
             while(t--)
             {
                 printf("%d ",i);
                 k--;
                 if(k==0)
                 {
                     printf("\n");
                     return 0;
                 }
             }
         }

    }
    printf("\n");

    return 0;
}
全部评论

相关推荐

找不到工作死了算了:没事的,雨英,hr肯主动告知结果已经超越大部分hr了
点赞 评论 收藏
分享
10-24 11:10
山西大学 Java
若梦难了:哥们,面试挂是很正常的。我大中厂终面挂,加起来快10次了,继续努力吧。
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务