题目传送门:F. Network Coverage
题目描述
有n个城市和n个网络站,分布呈环状交替,第i个网络站只为第i个和第i + 1个城市提供服务;
第i个城市有ai个家庭,第i个网络站可以为bi个家庭提供服务;
问是否能满足所有家庭需求?可以输出YES,否则输出NO
思路
显然,不合理的分配会使得某些城市无法满足需求,比如一个网络站为前一个城市分配过多,可能会导致后一个城市即使加上后一个网络站的所有分配量也无法满足需求。
那么我们如何来判断是否能满足需求呢?本题有和两种做法,这里先讲后一种做法思路(后一种做法更容易想到)
通过思考我们可以发现,当我们增加第i个网络站给第i + 1个城市的分配量时,从i + 1个城市开始(一直绕着圈到第i - 1个城市)各个城市接收到服务的家庭数量不会减少(增加或者不变),这里就体现出了单调性。
既然是单调性我们就可以通过二分第i个网络站给第i座城市的分配量,然后O(n)分配(第i个网络站先满足第i个城市需求,然后剩余分配量给第i + 1个城市,这里体现了贪心,显然当某个网络站分配量确定时,整个环各个网络站的分配是唯一确定的),最后看第i座城市能否满足需求即可。(为了方便起见,我二分第1个网络站给第1座城市的分配量)
那么如何二分呢?
比如第1个网络站给第1个城市分配x (0 <= x <= min(a[1], b[1]) ),那么在第2个到第n个城市能满足需求的情况下,x越大越好(因为资源分配一圈再分配回来时在某些城市资源会存在空置,比如第1个网络站把资源全部分配给第2个城市,那么在第1个网络站资源大于第2个城市需求时,就会存在资源空置,并且第1个网络站无法跨城市把资源分配给第3个城市用)
最后只要判断第n个网络站剩余分配量加上x能不能满足第1个城市需求即可。
代码
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> pll;
const int mod = 1e9 + 7;
const int N = 1e6 + 10;
const int INF = 0x3f3f3f3f;
ll qpow(ll base, ll n){ll ans = 1; while (n){if (n & 1) ans = ans * base % mod; base = base * base % mod; n >>= 1;} return ans;}
ll gcd(ll a, ll b){return b ? gcd(b, a % b) : a;}
int a[N], b[N], n;
int judge(int x){
for (int i = 2; i <= n; ++ i){
int res = b[i - 1] - x;//第i - 1个网络站剩余分配量
if (res + b[i] < a[i]) return -1;
x = a[i] > res ? a[i] - res : 0;//第i个网络站给第i个城市的分配量
//如果前一个网络站满足第i个城市需求,那么第i个网络站无需分配资源
//这里前一个网络站就可能存在资源过剩空置导致资源浪费
}
return b[n] - x;
}
int main()
{
int t;
cin >> t;
while (t --){
cin >> n;
for (int i = 1; i <= n; ++ i) scanf("%d", &a[i]);//城市家庭数
for (int i = 1; i <= n; ++ i) scanf("%d", &b[i]);//网络站供应家庭数
int l = 0, r = min(a[1], b[1]);
while (l < r){
int m = (l + r + 1) >> 1;//第1个网络站供应第1个城市m个家庭
if (judge(m) == -1) r = m - 1;//无法满足第2到n个城市需求,减少对第1个城市分配从而增加第二个城市分配量
else l = m;
}
printf("%s\n", l + judge(l) >= a[1] ? "YES" : "NO");
}
return 0;
}