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)后,有两种结果:

  1. 一种是断流(由于\(b_i\)\(a_i\)贡献太多,导致对\(a_{i+1}\)贡献过少,导致后面断流);
  2. 一种是流一圈后由\(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;
    }
}
posted @ 2020-06-26 22:47  limil  阅读(399)  评论(0编辑  收藏  举报