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 }
View Code

 

posted @ 2018-11-18 14:26  euzmin  阅读(395)  评论(0编辑  收藏  举报