昨晚梦到自己把这道题的题解写了 , 既然梦到了 , 那就写吧
题目链接
https://codeforces.com/problemset/problem/1373/F
题目大意
有 N 个城市 , 这 N 个城市围成一个圈 ( N + 1 = 1 )
其中第 i 个城市需要 ai 台设备 , 而第 i 个城市本身含有 bi 台设备
现在告诉你第 i 个城市的设备可以提供给它自己或第 i + 1 个城市
问是否能通过合理的分配使得每个城市的设备都满足需求
解题思路
第 i 个城市最后的设备数 = 第 i 个城市提供给自身的设备数 + 第 i - 1个城市提供给它的设备数
当一个城市的提供给自身的设备数确定之后 , 剩下的城市就可以通过贪心来分配
那么暴力的做法就是枚举第一个城市分配给自身的设备数 K1 , 然后判断是否可行
而通过观察我们会发现 , K1 越大 , 第 2 ~ n 个城市可能被分配的个数就会减少
K1 越小 , 第 n 个城市给第一个城市分配的设备数加上 K1 就可能小于 a1
于是我们可以对 K1 二分 , 当第 2 ~ n 个城市不够分配时 , 我们让 R = mid - 1
当第 n 个城市给第一个城市分配的设备数 + K1 < ai 时 , 我们让 L = mid + 1
当两者都合法时 , 我们直接结束二分输出答案即可 , 复杂度 NlogN
AC_Code
#include<bits/stdc++.h> using namespace std; const int N = 1e6 + 10; int a[N] , b[N] , n , t; int check(int mid) { int pre = b[1] - mid; for(int i = 2 ; i <= n ; i ++) { pre = min(b[i] + pre - a[i] , b[i]); if(pre < 0) return -1; } if(pre + mid >= a[1]) return 1; else return 0; } signed main() { ios::sync_with_stdio(false) , cin.tie(0); cin >> t; while(t --) { cin >> n; for(int i = 1 ; i <= n ; i ++) cin >> a[i]; for(int i = 1 ; i <= n ; i ++) cin >> b[i]; int l = 0 , r = b[1] , mid , flag = 0; while(l <= r) { int mid = l + r >> 1; if(check(mid) == -1) r = mid - 1; else if(!check(mid)) l = mid + 1; else { flag = 1 ; break ; } } if(!flag) cout << "NO\n"; else cout << "YES\n"; } return 0; }