Codeforces Round #143 (Div. 2) C. To Add or Not to Add 二分

http://codeforces.ru/contest/231/problem/C

题意:

给你n个数,你每次可以使其中的一个数加1,最多的加1次数为k,可以选择同一个数连续加但必须小于k。求使得小于等于k次加1操作后原序列中出现的相同元素最多的元素的个数,以及这个元素的值。

思路:

比赛时想了O(n^2)的做法写了一下超时,这是必然,我们首先对其进行从小到达排序然后枚举位置i ,从i - 1到1 枚举查看加到a[i]需要加1的次数直到k剩余个数不满足。这样的O(n^2)显然超时。要怎么优化呢?  开始想了二分枚举到底枚举什么自己糊涂了,没想到。这里看对于个数枚举。当我们枚举到 i 时,在区间[1,i - 1](前提是从小到达排序)中枚举满足加小于等于k的1满足等于a[i]的个数,这里我们求需要k的个数因为需要1的个数与区间满足条件的元素的个数呈单调性。 needk = m*a[i] - (sum[i] - sum[i - m]).这样就好了。。

PS:这里的时间复杂度为O(n*logn)用cin,cout  tle无语, 注意数据类型的把空

 

View Code
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>

#define CL(a,num) memset((a),(num),sizeof(a))
#define iabs(x)  ((x) > 0 ? (x) : -(x))
#define Min(a,b) (a) > (b)? (b):(a)
#define Max(a,b) (a) > (b)? (a):(b)

#define ll long long
#define inf 0x7f7f7f7f
#define MOD 1073741824
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define test puts("<------------------->")
#define maxn 100007
#define M 150
#define N 100007
using namespace std;
//freopen("data.in","r",stdin);

int a[N];
ll sum[N];

int bSearch(int l,int r,int k,int pos){
    int ans = 1;
    while (l <= r){
        int m = (l + r)>>1;
        ll tmp = (ll)m*a[pos] - (sum[pos] - sum[pos - m]);//here could overflow
        if (tmp <= k){
            l = m + 1;
            ans = m;
        }
        else{
            r = m - 1;
        }
    }
    return ans;
}
int main(){
    //freopen("data.in","r",stdin);
    int i;
    int n,k;
    while (~scanf("%d%d",&n,&k)){
        sum[0] = 0;
        for (i = 1; i <= n; ++i) scanf("%d",&a[i]);
        sort(a + 1,a + 1 + n);
        for (i = 1; i <= n; ++i) sum[i] = sum[i - 1] + a[i];
        int ans = 1;
        int mk = a[1];
        int tmp;
        for (i = 2; i <= n; ++i){
            tmp = bSearch(1,i,k,i);
            if (ans < tmp){
                ans = tmp;
                mk = a[i];
            }
        }
        printf("%d %d\n",ans,mk);
    }
    return 0;
}

 

posted @ 2012-10-28 10:01  E_star  阅读(190)  评论(0编辑  收藏  举报