题目链接: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
**/