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