传送门:点击打开链接
题意:沙漠中有许多块矩形水源,水源不相交,问能否找到一根中轴线,使得轴线左边的水源面积大于等于右边的水源面积。在满足两个面积之差最小的情况下,使得轴线靠近右端点
思路:只能说当时现场赛的时候太脑残了,。要分两次二分!一次二分是做不到的。第一次二分求出左边面积大于等于右边面积时,使两边之差最小,那么此时左边面积等于多少
第二次二分再去让左边面积等于这么多,然后更加靠近右边的位置是哪里。
那么这样下来,就能求出答案了- -
#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;
}