二分 hihoCoder1249 Xiongnu's Land

传送门:点击打开链接

题意:沙漠中有许多块矩形水源,水源不相交,问能否找到一根中轴线,使得轴线左边的水源面积大于等于右边的水源面积。在满足两个面积之差最小的情况下,使得轴线靠近右端点

思路:只能说当时现场赛的时候太脑残了,。要分两次二分!一次二分是做不到的。第一次二分求出左边面积大于等于右边面积时,使两边之差最小,那么此时左边面积等于多少

第二次二分再去让左边面积等于这么多,然后更加靠近右边的位置是哪里。

那么这样下来,就能求出答案了- -

#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define fuck(x) cout<<"["<<x<<"]"
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w+",stdout)
using namespace std;
typedef long long LL;

const int MX = 10000 + 5;
struct Seg {
    int l, r, h;
} S[MX];

LL sum;
int n, Rig;

LL get(int x) {
    LL ret = 0;
    for(int i = 1; i <= n; i++) {
        if(S[i].l < x) {
            ret += (LL)(min(S[i].r, x) - S[i].l) * S[i].h;
        }
    }
    return ret;
}

int solve() {
    int l = 0, r = Rig, m;
    while(l <= r) {
        m = (l + r) >> 1;
        LL left = get(m);
        if(left >= sum - left) r = m - 1;
        else l = m + 1;
    }

    LL ans = get(r + 1);

    l = 0, r = Rig;
    while(l <= r) {
        m = (l + r) >> 1;
        LL left = get(m);
        if(left > ans) r = m - 1;
        else l = m + 1;
    }
    return l - 1;
}

int main() {
    int T; //FIN;
    scanf("%d", &T);
    while(T--) {
        sum = 0;
        scanf("%d%d", &Rig, &n);
        for(int i = 1; i <= n; i++) {
            scanf("%d%*d%d%d", &S[i].l, &S[i].r, &S[i].h);
            S[i].r += S[i].l;
            sum += (LL)(S[i].r - S[i].l) * S[i].h;
        }
        printf("%d\n", solve());
    }
    return 0;
}


你可能感兴趣的:(二分 hihoCoder1249 Xiongnu's Land)