题意:有多个矩形分布在[0, 0]到[R, R]的的范围内,画一条竖线分割成两块矩形,使得左边包括矩形的面积大于等于右边的面积,在这个前提下使得画的竖线尽量远
分析:二分答案,当面积相等时,判断再往右一个单位是否还可以相等,若不行则答案唯一确定,否则可以往右移动,即最后的竖线要不在一个矩形内或者在矩形边缘时最优.
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e4 + 10; struct Point { int x1, y, w, h, x2; bool operator < (const Point &r) const { return x1 < r.x1; } }p[N]; int n, R; ll tot; ll cal(int mid) { ll ret = 0; for (int i=1; i<=n; ++i) { if (p[i].x1 >= mid) break; else if (p[i].x2 <= mid) ret += 1ll * p[i].w * p[i].h; else { ret += 1ll * (mid - p[i].x1) * p[i].h; } } return ret; } bool check(int mid) { for (int i=1; i<=n; ++i) { if (p[i].x1 < mid && mid < p[i].x2) return true; } return false; } int solve() { sort (p+1, p+1+n); int l = 0, r = R; while (l + 1 < r) { int mid = (l + r) >> 1; ll LA = cal (mid); ll RA = tot - LA; if (LA < RA) l = mid; else if (LA == RA) { if (check (mid) || check (mid + 1)) { return mid; } else l = mid; } else { r = mid; } } if (check (r)) return r; for (int i=1; i<=n; ++i) { if (p[i].x1 >= r) return p[i].x1; } return R; } int main(void) { int T; scanf ("%d", &T); while (T--) { scanf ("%d", &R); scanf ("%d", &n); tot = 0; for (int i=1; i<=n; ++i) { scanf ("%d%d%d%d", &p[i].x1, &p[i].y, &p[i].w, &p[i].h); p[i].x2 = p[i].x1 + p[i].w; tot += 1ll * p[i].w * p[i].h; //? } int ans = solve (); printf ("%d ", ans); } return 0; }