题意:
有 n n n 个城市围城一圈,第 i i i 个城市有 a i a_i ai 个网络需求,每个城市建有一个网络站,第 i i i 个城市的网络站可以提供 b i b_i bi 个网络需求;且 第 i i i 个城市的网络站只能提供需求给第 i i i 和 i + 1 i+1 i+1 个城市 ( n + 1 = 1 ) (n+1=1) (n+1=1),问是否存在合理分配使得所有城市的所有需求都被满足
分析:
围成一圈,所以只要确定一个网络站的分配,就可以贪心判断是否有解;考虑城市 i i i 中网络站对需求的分配 k k k (即网络站 i i i 对城市 i i i 的分配):
- 如果 k k k 过大,那么后面就会造成断流,即某个城市得不到足够的分配;
- 如果 k k k 过小,后面不会有断流,但网络站 i − 1 i-1 i−1 就没有足够的资源分配给城市 i i i ,使得城市 i i i 的需求得到满足,我们设这个资源为 c c c,即 k + c < a i k+c<a_i k+c<ai ;
所以对于第 i i i 个城市,有解的分配 k k k 实际上是一个连续的区间,而在这个范围内, k k k 每 − 1 -1 −1 ,那么 c c c 至多 + 1 +1 +1 ,因为如果中间产生满流了,那么此时 k k k 再怎么减小, c c c 也不变;所以我们可以二分,在 c > = 0 c>=0 c>=0 的情况下,找到最大的 k k k
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define frep(i,a,b) for(int i=a;i>=b;i--)
const int N = 1E6+10;
int a[N],b[N],n;
int check(int M)
{
int pre=b[1]-M;
rep(i,2,n)
{
pre=min(pre,a[i]);
pre+=b[i];
pre-=a[i];
if(pre<0) return -1;
}
return pre;
}
int main()
{
//freopen("1.txt","r",stdin);
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int t; cin>>t;
while(t--)
{
cin>>n;
rep(i,1,n)cin>>a[i];
rep(i,1,n)cin>>b[i];
int L=0,R=min(b[1],a[1]);
while(L<=R)
{
int M=(L+R)>>1;
if(check(M)>=0) L=M+1;
else R=M-1;
}
if(R>=0&&R+check(R)>=a[1]) cout<<"YES";
else cout<<"NO";
cout<<endl;
}
}