【Codeforces 1373F】Network Coverage 二分

題目鏈接:https://codeforces.ml/contest/1373/problem/F

題目大意:

給出兩段序列a_i,b_i,a_i代表第i個點的商品需求量,b_i代表第i個點的供應量

b_i可以爲a_i與a_(i+1)供應商品

問是否有一種分配方案使得a_i都滿足需求?

題目思路:

首先確定,如果存在一種方案的話,b_i一定會向a_i+1提供了一定數目,但是數目不確定

所以可以想到去二分當前的數目,來判斷提供的數目是否合法

此時從任意的bi開始是都可以的,爲了簡便從b_1開始

所以有以下三種情況:

如果中途出現,b[i] 全部給自己 也不能滿足a[i],那麼說明a[1]給少了

如果最後發現,d[1]剩餘的不夠了,那麼說明給多了

否則,即爲合法情況

所以,該函數滿足單調性,進行二分即可

看到有O(n)的做法,但是沒有理解,如果有大佬在評論下分享再好不過了

Code:

/*** keep hungry and calm CoolGuang!***/
#include <bits/stdc++.h>
#pragma GCC optimize(3)
//#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=2e18;
const int maxn=1e6+6;
const int mod=1000000007 ;
const double eps=1e-15;
inline bool read(ll &num)
{char in;bool IsN=false;
    in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
int s = 0;
ll num[maxn],dp[maxn];
ll a[maxn],b[maxn],c[maxn],d[maxn];
int check(ll x){
    for(int i=1;i<=n;i++) d[i] = b[i],c[i] = 0;
    d[1] -= x;
    c[2] += x;
    for(int i=2;i<=n;i++){
        int diff = a[i] - c[i];
        int aim = i+1>n?1:i+1;
        if(diff < 0) c[aim] += d[i];
        else{
            if(d[i]>=diff){
                c[aim] += d[i]-diff;
                c[i] = a[i];
            }
            else return 1;///分配少了
        }
       // debug(c[i]);
    }
   // for(int i=1;i<=n;i++) printf("%lld ",c[i]);
    //printf("\n");
    if(c[1]+d[1]<a[1]) return 2;///分配給a[2]多了
    return 3;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--){
        read(n);
        for(int i=1;i<=n;i++) read(a[i]);
        for(int i=1;i<=n;i++) read(b[i]);
        int l = 0,r = b[1];
        int f = 0;
        //debug(check(2));
        while(l<=r){
            int mid = (l+r)/2;

            int flag = check(mid);
            if(flag == 3){
                f = 1;
                break;
            }
            else if(flag==1) l = mid + 1;
            else if(flag==2) r = mid - 1;
        }
        if(f) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}
/**
0 3 4
2 0 0
**/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章