hdu6383 p1m2(二分答案)

p1m2

题目传送门

解题思路

因为x都是非负数,且每一次操作其实就是把总和减少了1,所以可以得出最后都可以到达稳定。最后稳定的数的下界是0,最大也不会超过其初始数的最大值,所以可以用二分答案来求解。每次二分,我们统计要到达出来的二分值,每个数进行上升操作的次数总和以及下降次数的总和。如果上升次数大于下降次数,说明这个答案偏大了则r=mid-1,如果上升次数小于下降次数,由于答案是要求稳定后的最小值,而我们计算是使所有数都变得一样,所以下降次数其实是可以大于上升次数的,所以此时和相等时一样,都是使l=mid;

代码如下

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;

inline int read(){
    int res = 0, w = 0; char ch = 0;
    while(!isdigit(ch)){
        w |= ch == '-', ch = getchar();
    }
    while(isdigit(ch)){
        res = (res << 3) + (res << 1) + (ch ^ 48);
        ch = getchar();
    }
    return w ? -res : res;
}

const int N = 300005;

int x[N];
int n;

bool work(int k)
{
    ll l = 0, r = 0;
    for(int i = 1; i <= n; i ++){
        if(x[i] < k)
            r += k - x[i];
        else {
            l += (x[i] - k + 1) / 2;
            r += (x[i] - k) % 2;
        }
    }
    return l >= r;
}

int main()
{
    int t;
    cin >> t;
    while(t --){
        n = read();
        int l = 0, r = 0;
        for(int i = 1; i <= n; i ++)
            x[i] = read(), r = max(r, x[i]);
        int mid = (l + r + 1) / 2;
        while(l < r){
            if(work(mid))
                l = mid;
            else
                r = mid - 1;
            mid = (l + r + 1) / 2;
        }
        printf("%d\n", mid);
    }
    return 0;
}
posted @ 2019-07-19 10:25  whisperlzw  阅读(121)  评论(0编辑  收藏  举报