1077E Thematic Contests 【二分答案】
题目:戳这里
题意:n个数代表n个problem,每个数的值代表这个问题的topic,让我们挑出一些problems,满足挑出problems的topic是首项为a1公比为2的等比数列(每种topic只能选一次。问最多能挑出多少个problems。
解题思路:可以看出这道题只和每个topic的数量有关,我们记录每个topic的数量并排序。n的范围是2e5,也就是最后选出来的topic最多21个。所以只需要枚举等比数列的a1,二分查找是否有满足条件的a1*2^x即可。注意每种topic只能选一次,所以每次找出一个topic,二分的范围就要缩小一下,具体看代码。
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 ll a[maxn]; 7 map<ll, int>mp; 8 int cnt[maxn]; 9 int main(){ 10 int n; 11 scanf("%d", &n); 12 for(int i = 1; i <= n; ++i) { 13 scanf("%lld", a+i); 14 ++mp[a[i]]; 15 } 16 int newn = 0, maxx = 0; 17 for(auto i: mp) { 18 cnt[++newn] = i.second; 19 maxx = max(maxx, i.second); 20 } 21 sort(cnt + 1, cnt + 1 + newn); 22 int ans = 0; 23 for(int i = 1; i <= maxx; ++i) {//21 24 int pos = 1, mul = 1; 25 int sum = 0; 26 while(pos <= newn) { 27 pos = lower_bound(cnt + pos, cnt + 1 + newn,mul * i) - cnt; 28 // printf("%d pos, %d mul %d sum\n", pos, mul,sum); 29 if(pos > newn) break; 30 else { 31 sum += mul * i; 32 ++pos; 33 } 34 mul *= 2; 35 } 36 ans = max(ans, sum); 37 } 38 printf("%d\n", ans); 39 return 0; 40 }