Codeforces 1077D Cutting Out(二分答案)

题目链接:Cutting Out

题意:给定一个n长度的数字序列s,要求得到一个k长度的数字序列t,每次从s序列中删掉完整的序列t,求出能删次数最多的那个数字序列t。

题解:数字序列s先转换成不重复的数字序列,并记录各个数字重复的次数,然后按照重复次数从大到小排序。二分最大删除次数,最后再输出对应的序列t。

 1 #include <map>
 2 #include <cstdio>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int N=2e5+10;
 8 int n,k,x,id=0;
 9 map <int,int> m;
10 struct node{
11     int val,cnt;
12 }p[N];
13 
14 bool cmp(node x,node y){
15     return x.cnt>y.cnt;
16 }
17 
18 bool check(int mid){
19     int need=k;
20     for(int i=1;i<=id;i++){
21         if(need==0) return true;
22         int tmp=p[i].cnt/mid;
23         if(tmp>=1){
24             if(need>=tmp) need-=tmp;
25             else return true;
26         }
27         else return false;
28     }
29     if(need>0) return false;
30     return true;
31 }
32 
33 int main(){
34     scanf("%d%d",&n,&k);
35     for(int i=1;i<=n;i++){
36         scanf("%d",&x);
37         if(!m[x]) id++,m[x]=id,p[id].val=x;
38         p[m[x]].cnt++;
39     }
40     sort(p+1,p+1+id,cmp);
41     int l=1,r=N,ans=1;
42     while(l<=r){
43         int mid=(l+r)/2;
44         if(check(mid)) l=mid+1,ans=mid;
45         else r=mid-1;
46     }
47     for(int i=1;i<=id;i++){
48         if(k==0) break;
49         int tmp=p[i].cnt/ans;
50         if(tmp>=1){
51             if(k>=tmp){
52                 k-=tmp;
53                 for(int j=1;j<=tmp;j++) printf("%d ",p[i].val);
54             }
55             else{
56                 for(int j=1;j<=k;j++) printf("%d ",p[i].val);
57                 k=0;
58             }
59         }
60     }
61     return 0;
62 }
View Code

 

posted @ 2018-11-20 12:22  pavtlly  阅读(448)  评论(0编辑  收藏  举报