codeforces 1077D Cutting Out 【二分】
题目:戳这里
题意:给n个数的数组,要求找k个数满足,这k个数在数组中出现的次数最多。
解题思路:k个数每个数出现次数都要最大化,可以想到二分下限,主要是正确的二分不好写。
附ac代码:
1 #include <bits/stdc++.h> 2 typedef long long ll; 3 const int maxn = 1e6+10; 4 const ll inf = 1e18; 5 using namespace std; 6 int cnt[maxn]; 7 int s[maxn]; 8 int n, k; 9 int ans[maxn]; 10 int len = 0; 11 int check(int m,int n) { 12 int x = 0; 13 len = 0; 14 for(int i = 1; i <= n; ++i) { 15 x += cnt[s[i]] / m; 16 if(cnt[s[i]] / m > 0) { 17 ans[++len] = s[i]; 18 } 19 } 20 if(x >= k) return 1; 21 else return 0; 22 } 23 int main(){ 24 25 scanf("%d %d", &n, &k); 26 for(int i = 1; i <= n; ++i) { 27 scanf("%d", &s[i]); 28 cnt[s[i]]++; 29 } 30 31 int l = 1, r = n; 32 sort(s + 1, s + 1 + n); 33 n = unique(s + 1, s +1 + n) - s -1; 34 ll sum = 0; 35 while(l <= r) { 36 int m = (l + r) / 2; 37 int u = check(m, n); 38 if(u == 1) l = m + 1, sum = m;//如果u>1,则m本身一直满足条件 39 else r = m - 1; 40 } 41 int now = 0; 42 for(int i = 1; i <= n; ++i) { 43 for(int j = 1; j <= cnt[s[i]] / sum; ++j) {//注意除以的是sum,我就是这里忘改了所以最后怎么都没过。。 44 printf("%d ", s[i]); 45 ++now; 46 if(now == k) return 0; 47 } 48 } 49 return 0; 50 }