Codeforces 1373F - Network Coverage (二分)
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 '\n'
#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;
}
}