題目鏈接: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
**/