题意:给你一个数列(好吧,又是数列= =),可对这个数列中的某些数加一个值,但加的总值不能超过k。求在这些操作下,使得数列中的某个数出现的次数最多。
这个题纯靠yy,我们可以依次从数列中最小的数开始枚举,但复杂度为O(n^2),铁定超时。但是可以优化之,大大降低复杂度。首先对数列排序,然后依次从左往右开始枚举,那么这里可以有一个状态转移:假设当前状态还剩余d可操作,满足数相等的最左端的数的位置为l,那么新加一个数num[i+1],只要比较(num[i+1]-num[i])*(i-l+1)与d的关系即可,来改变l的位置,那么就能很快求出下一状态。
My code:
//STATUS:C++_AC_78MS_400KB
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#define LL __int64
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define mem(a,b) memset(a,b,sizeof(a))
const int MAX=100010,INF=200000000,MOD=1000000007;
const double esp=1e-6;
int cmp(const void *a,const void *b){
return *(int*)a - *(int*)b;
}
int num[MAX];
int n;
LL k;
int main()
{
// freopen("in.txt","r",stdin);
int i,j,l,max_cou,max_num;
LL d;
while(~scanf("%d%I64d",&n,&k))
{
for(i=1;i<=n;i++)
scanf("%d",&num[i]);
qsort(num+1,n,sizeof(int),cmp);
l=1;
max_cou=1,max_num=num[1];
for(i=2;i<=n;i++){
d=(LL)(i-l)*(LL)(num[i]-num[i-1]);
k-=d;
while(k>0 && l>1 && num[i]-num[l-1]>=k){
l--;
k-=num[i]-num[l];
}
while(k<0 && l<i){
k+=num[i]-num[l];
l++;
}
if(i-l+1>max_cou){
max_cou=i-l+1;
max_num=num[i];
}
}
printf("%d %d\n",max_cou,max_num);
}
return 0;
}