https://www.luogu.com.cn/problem/CF1700D
题面翻译:
有
n
n
n个容器,第
i
i
i个容器容量为
v
i
v_i
vi升,可以容纳
[
0
,
v
i
]
[0,v_i]
[0,vi]升的水。
满出去的水会将从容器 i i i转移到容器 i + 1 i+1 i+1,如果 i + 1 i+1 i+1也满了会转移得更远。满出最后一个容器的水会倒到河中。
现在要将所有容器填满。你可以选择一些容器注水,让这些容器每秒进入一升水。 q q q次询问,问最初所有容器都是空的,最少选择多少个容器注水使得 t i t_i ti秒内能填满所有容器。
1 ≤ n , q ≤ 2 × 1 0 5 1\leq n,q\leq 2\times 10^5 1≤n,q≤2×105, 1 ≤ v i , t i ≤ 1 0 9 1\leq v_i,t_i\leq 10^9 1≤vi,ti≤109。
题目描述:
Recently in Divanovo, a huge river locks system was built. There are now
n
n
n locks, the
i
i
i -th of them has the volume of
v
i
v_i
vi liters, so that it can contain any amount of water between
0
0
0 and
v
i
v_i
vi liters. Each lock has a pipe attached to it. When the pipe is open,
1
1
1 liter of water enters the lock every second.
The locks system is built in a way to immediately transfer all water exceeding the volume of the lock
i
i
i to the lock
i
+
1
i + 1
i+1 . If the lock
i
+
1
i + 1
i+1 is also full, water will be transferred further. Water exceeding the volume of the last lock pours out to the river.
The picture illustrates
5
5
5 locks with two open pipes at locks
1
1
1 and
3
3
3 . Because locks
1
1
1 ,
3
3
3 , and
4
4
4 are already filled, effectively the water goes to locks
2
2
2 and
5
5
5 .To make all locks work, you need to completely fill each one of them. The mayor of Divanovo is interested in
q
q
q independent queries. For each query, suppose that initially all locks are empty and all pipes are closed. Then, some pipes are opened simultaneously. For the
j
j
j -th query the mayor asks you to calculate the minimum number of pipes to open so that all locks are filled no later than after
t
j
t_j
tj seconds.
Please help the mayor to solve this tricky problem and answer his queries.
输入格式:
The first lines contains one integer
n
n
n (
1
≤
n
≤
200
000
1 \le n \le 200\,000
1≤n≤200000 ) — the number of locks.
The second lines contains n n n integers v 1 , v 2 , … , v n v_1, v_2, \dots, v_n v1,v2,…,vn ( 1 ≤ v i ≤ 1 0 9 1 \le v_i \le 10^9 1≤vi≤109 )) — volumes of the locks.
The third line contains one integer q q q ( 1 ≤ q ≤ 200 000 1 \le q \le 200\,000 1≤q≤200000 ) — the number of queries.
Each of the next q q q lines contains one integer t j t_j tj ( 1 ≤ t j ≤ 1 0 9 1 \le t_j \le 10^9 1≤tj≤109 ) — the number of seconds you have to fill all the locks in the query j j j .
输出格式:
Print
q
q
q integers. The
j
j
j -th of them should be equal to the minimum number of pipes to turn on so that after
t
j
t_j
tj seconds all of the locks are filled. If it is impossible to fill all of the locks in given time, print
−
1
-1
−1 .
注意题目中说,每个水槽满了之后水都会漫到其右边那个水槽里,所以如果能装满的话,优先开最左边的若干个水龙头,这样使得水漫出右边界的情况尽可能少的发生。如果只考虑第 1 1 1个水槽,则至少需要 v 1 v_1 v1单位时间才能装满;如果只考虑前 2 2 2个水槽,那么如果两个水龙头一起开,如果不溢出的话,花的时间最少是 ⌈ v 1 + v 2 2 ⌉ \lceil \frac{v_1+v_2}{2} \rceil ⌈2v1+v2⌉,但是如果有溢出,意味着第 1 1 1个水槽还没装满,但是第 2 2 2个水槽已经漏水了,这个时候花的时间是 v 1 v_1 v1,所以综合两种情况,时间最少是 max { v 1 , ⌈ v 1 + v 2 2 ⌉ } \max\{v_1,\lceil \frac{v_1+v_2}{2} \rceil\} max{v1,⌈2v1+v2⌉},以此类推,要装满所有水槽,时间最少是 t 0 = max k ∑ i = 1 k v i k t_0=\max_k \frac{\sum_{i=1}^k v_i}{k} t0=maxkk∑i=1kvi,先求出这个 t 0 t_0 t0,如果给出的询问 t < t 0 t<t_0 t<t0直接输出 − 1 -1 −1。
如果 t ≥ t 0 t\ge t_0 t≥t0,那么至少是有解的,设解为 k k k,则 k ≥ ⌈ ∑ i = 1 n v i t ⌉ = k 0 k\ge \lceil \frac{\sum_{i=1}^n v_i}{t} \rceil=k_0 k≥⌈t∑i=1nvi⌉=k0,但是 k 0 k_0 k0个水龙头事实上已经足够了,因为水只会向右边漫,只要开前 k 0 k_0 k0个水龙头,过了 t t t时间后,显然前 k 0 k_0 k0个水槽是满的,溢出前 k 0 k_0 k0个水槽的水刚好保证后面的水槽装满(可能有溢出,因为是上取整)。代码如下:
#include <iostream>
using namespace std;
using LL = long long;
const int N = 2e5 + 10;
int n, q;
LL a[N], low;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
a[i] += a[i - 1];
}
for (int i = 1; i <= n; i++) low = max(low, (a[i] + i - 1) / i);
scanf("%d", &q);
while (q--) {
long t;
scanf("%lld", &t);
if (t < low) puts("-1");
else printf("%lld\n", (a[n] + t - 1) / t);
}
}
预处理时间复杂度 O ( n ) O(n) O(n),每次询问 O ( 1 ) O(1) O(1),空间 O ( 1 ) O(1) O(1),