【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
**/

猜你喜欢

转载自blog.csdn.net/qq_43857314/article/details/106982440