Description
思路
如果我们知道某一个站(b_i)到对(a_i)的贡献是多少,那么就可以用贪心求解(因为这样我们就知道(b_i)对(a_{i+1})的贡献,从而知道(b_{i+1})对(a_{i+1})...)。所以可以考虑二分(b_i)对(a_i)的贡献。
可以把(b_i)对(a_i)的贡献看作流水,这里(a_i)就是容量。
确定了(b_i)对(a_i)的贡献(设为c)后,有两种结果:
- 一种是断流(由于(b_i)对(a_i)贡献太多,导致对(a_{i+1})贡献过少,导致后面断流);
- 一种是流一圈后由(b_{i-1})流回(a_i)(设流回的量为x)。对于后一种,(b_i)对(a_i)的贡献每减少1,x至多增加1,因为流一圈过程中可能有地方满流了,继续增加流量,x也不会增加。
所以二分找到使得流回量x>0的最大的c。这个就是边界情况,判断x+c是否大于等于(a_i)即可。
这里取(a_i)为(a_1)。
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <cstring>
#include <string>
#include <stack>
#include <deque>
#include <cmath>
#include <iomanip>
#include <cctype>
#define endl '
'
#define IOS std::ios::sync_with_stdio(0);
#define FILE freopen("..//data_generator//in.txt","r",stdin),freopen("res.txt","w",stdout)
#define FI freopen("..//data_generator//in.txt","r",stdin)
#define FO freopen("res.txt","w",stdout)
#define pb push_back
#define mp make_pair
#define seteps(N) fixed << setprecision(N)
typedef long long ll;
using namespace std;
/*-----------------------------------------------------------------*/
#define INF 0x3f3f3f3f
const int N = 1e6 + 10;
const double eps = 1e-8;
int arr[N];
int brr[N];
int check(int x, int n) {
int out = brr[1] - x;
for(int i = 2; i <= n; i++) {
int p = i > n ? i - n : i;
int cap = arr[p];
cap = max(cap - out, 0);
if(cap > brr[p]) return -1;
out = brr[p] - cap;
}
return out;
}
int main() {
IOS;
int t;
cin >> t;
while(t--) {
int n;
cin >> n;
for(int i = 1; i <= n; i++) cin >> arr[i];
for(int i = 1; i <= n; i++) cin >> brr[i];
int l = 0, r = brr[1];
while(l <= r) {
int mid = (l + r) / 2;
if(check(mid, n) >= 0) {
l = mid + 1;
} else {
r = mid - 1;
}
}
if(r < 0) cout << "NO" << endl; //一直断流
else if(r + check(r, n) >= arr[1]) cout << "YES" << endl;
else cout << "NO" << endl;
}
}