对于每一个 \(i\) 可以看作一个管道。赋予三个信息:
- \(\text{minIn}_i\) 表示至少要从上一家 \(i - 1\) 得到连接数,才能正常供给 \(i\) 城市
- \(\text{minOut}_i\) 最坏情况下最少给下一家 \(i + 1\) 多少连接数
- \(\text{maxOut}_i\) 表示最多能给下一家 \(i + 1\) 多少连接数
三个变量维护完毕,我们发现我们可以通过某种方法合并两个相邻的管道,最后剩下一个管道,只需自检查 \(\text{minIn} \le \text{minOut}\) 即可(在最低限度下自我循环传输)。
合并需要分类讨论,假如合并 \(x, y\)。
- 首先必须满足 \(x.maxOut \ge y.minIn\),不然无论何时都满足不了。
- 如果 \(x.minOut \le y.minIn\),那么合并后的最低需求会变大,最大输出量也会被 \(x.maxOut\) 而限制
- 否则,最低输出量会被提高(或不变),最大输出量同样受到限制。
#include <cstdio>
#include <iostream>
using namespace std;
const int N = 1000005;
int n, a[N], b[N];
struct Pipe{
int minIn, minOut, maxOut;
};
Pipe get(int x, int y) {
if (x <= y) return (Pipe) { 0, y - x, y };
else return (Pipe) { x - y, 0, y };
}
Pipe merge(Pipe x, Pipe y) {
if (x.maxOut < y.minIn) return (Pipe) { -1, -1, -1 };
if (x.minOut <= y.minIn) return (Pipe) { x.minIn + y.minIn - x.minOut, y.minOut, min(y.maxOut, y.minOut + x.maxOut - y.minIn) };
else return (Pipe) { x.minIn, min(y.maxOut, y.minOut + x.minOut - y.minIn), min(y.maxOut, y.minOut + x.maxOut - y.minIn) };
}
int main() {
int T; scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", a + i);
for (int i = 1; i <= n; i++) scanf("%d", b + i);
Pipe cur = get(a[1], b[1]);
bool ok = true;
for (int i = 2; i <= n; i++) {
cur = merge(cur, get(a[i], b[i]));
if (cur.minIn == -1) { ok = false; break; }
}
if (cur.minOut < cur.minIn) ok = false;
puts(ok ? "YES" : "NO");
}
return 0;
}