CF1373F. Network Coverage

第$i$个供电所可以提供$b_i$给$i$,$(i+1)\% n$,$a_i$是所需要的电。

询问是否可以满足供电。

一个很神奇的二分,原来二分可以这样用。

考虑给$b_1$给$x$给$a_1$,那么显然后面可以递推过去

  • 如果在中途发生了供电不足,表示$x$需要少一点
  • 如果最后给$a_1$的满足不了$a_1$,那就让$b_i$多一点(此时最后$b_n$给$a_i$的只会增加或者不变,但不会减少)
  • 成功的就会在$[l,r]$之间。
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pii pair<ll, ll>
#define mk make_pair
const ll N = 1e6 + 10;
const ll mod = 1e9 + 7;

ll read()
{
ll x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-')
f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + c - '0', c = getchar();
return x * f;
}
ll a[N], b[N];
ll n;
int check(ll x)
{
ll p = b[1] - x;

for (ll i = 2; i <= n; i++)
{

p = min(b[i] + p - a[i], b[i]);

if (p < 0)
return -1;
}
if (p + x >= a[1])
return 1;
return 0;
}
int main()
{
ll T = read();
while (T--)
{
n = read();

for (ll i = 1; i <= n; i++)
a[i] = read();
for (ll i = 1; i <= n; i++)
b[i] = read();
ll l = 0, r = b[1];
ll ok = 0;
while (l <= r)
{
ll mid = (l + r) >> 1;
ll o = check(mid);
if (o == 1)
{

ok = 1;
break;
}
else if (o == -1)
{
r = mid - 1;
}
else
l = mid + 1;
}
puts(ok ? "YES"
: "NO");
}
}