本题让我重视到对lower_bound这个函数不是特别会用。
lower_bound(int * ,int *,int )
第一个参数是数组首地址,由于c++语言的特殊性,传入第一个参数可以是数组首地址+i,表示从数组第i个元素查找(对于下标从1开始的数组)
第二个参数是数组末位+1,这里可以把数组最后一位想象成INF,从头开始,如果发现哪一位大于等于要查找的数字就返回哪一位的地址。
第三个参数是要查找的数字。
然后这道题把所有数字离散化存入一个桶里从小到大排序
然后从第一位到最后一位暴力枚举
1每次都要枚举每一个小于等于这一位上的数字,
2对于枚举的每个数字,每次用lower_bound查找这一位数字后面的所有数字里面第一个大于等于这个数字的数。
3然后把数字乘二,位置移到查找到的位置,
直到位置超出数组总数后更新答案。
#include<bits/stdc++.h> using namespace std; int a[200010]; int aa[200010]; int b[200010]; int cnt[200010]; int tot; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); //将a[i]离散化 sort(a+1,a+n+1); aa[++tot]=a[1]; for(int i=2;i<=n;i++) { if(a[i]!=a[i-1]) { aa[++tot]=a[i]; //去重,tot是数组中有几个不同的数字 } } for(int i=1;i<=n;i++) { b[i]=lower_bound(aa+1,aa+tot+1,a[i])-aa;//lower_bound只对有序数组有效 } //b[i]里面存了离散化数组 //统计b[i]中有多少每个数字出现的个数 for(int i=1;i<=n;i++) { cnt[b[i]]++;//cnt有tot个数字 } sort(cnt+1,cnt+tot+1); int res=0; for(int i=1;i<=tot;i++) { int pos=i; for(int num=1;num<=cnt[pos];num++) { int now=0; int tmp=pos; int num1=num; while(tmp<=tot) { now+=num1; tmp=lower_bound(cnt+tmp+1,cnt+tot+1,num1*2)-cnt; num1*=2; } res=max(res,now); } } printf("%d\n",res); }