二分最大值x,判断x是否合法

一开始想的是记录一个suma,一个sumb,一个可飞走量val,从1扫到n,首先更新suma和sumb,然后判断suma和sumb是否大于x,是的话就让一些飞机飞走使得suma和sumb满足条件,当val小于0的时候返回false,否则val++,扫完以后都合法的话返回true。

这个思想大体上是对的,但是val++有问题,我忽略了E轨道或W轨道没有足够的飞机的情况,正确做法是记录一下val,再记录vala和valb,表示E轨道和W轨道可飞走的飞机数量,然后加点判断和更新就可以了,可以参考一下judge函数

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e4 + 10;
const int INF = 0x3f3f3f3f;
int t, n, a[maxn], b[maxn];
bool judge(int x) {
int suma = 0, sumb = 0, val = 0, vala = 0, valb = 0;
for (int i = 1; i <= n; i++) {
suma += a[i], sumb += b[i];
if (suma > x) {
val -= (suma-x);
vala -= (suma-x);
suma = x;
}
if (sumb > x) {
val -= (sumb-x);
valb -= (sumb-x);
sumb = x;
}
if (val < 0 || vala < 0 || valb < 0) return false;
val = min(suma+sumb, val+1);
vala = min(suma, vala+1);
valb = min(sumb, valb+1);
}
return true;
}
int solve() {
int l = 1, r = INF;
while (l <= r) {
int mid = (l + r)>>1;
if (judge(mid)) r = mid - 1;
else l = mid + 1;
}
return l-1;
}
int main() {
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d%d", &a[i], &b[i]);
printf("%d\n", solve());
}
return 0;
}