1. 程式人生 > >codeforces cf 521(div3) E題

codeforces cf 521(div3) E題

本題讓我重視到對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);
}