1. 程式人生 > >Codeforces 1077D Cutting Out(二分答案)

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