[ARC166D] Interval Counts 题解

Description

给定正整数 nn 和长度为 nn 的序列 xi,yix_i,y_i,保证 xix_i 单调递增。你要构造 mm 个区间 [Li,Ri][L_i,R_i]mm 由你指定),使每个 xix_i 恰好被 yiy_i 个区间包含。

最大化 mini=1m{RiLi}\min_{i=1}^m \{R_i-L_i\},并求该值。无穷输出 1-1

n2×105,1xi,yi109n\leq 2\times 10^5,1\leq x_i,y_i\leq 10^9

Solution

考虑贪心。

假设当前已经满足了 1i11\sim i-1 的限制,维护一个队列表示当前还没确定右端点的所有左端点。

如果 yi=yi1y_i=y_{i-1},那么只要让原来右端点接在 xi1x_{i-1} 的区间接到 xix_i 即可。

如果 yi>yi1y_i>y_{i-1},这说明原来的区间就算全部接到 xix_i 上还不够,需要再加 yiyi1y_i-y_{i-1} 个左端点为 xi1+1x_{i-1}+1 的区间。

如果 yi<yi1y_i<y_{i-1},说明要删掉 yi1yiy_{i-1}-y_i 个区间,由于要让最小值最大,所以需要删掉左端点最小的区间。

于是只要维护一个左端点递增的区间即可,由于区间数很多,顺便记一个这个左端点的个数即可。

时间复杂度:O(n)O(n)

Code

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
#include <bits/stdc++.h>

#define int int64_t

const int kMaxN = 2e5 + 5;

int n;
int x[kMaxN], y[kMaxN];
std::pair<int, int> q[kMaxN];

void dickdreamer() {
std::cin >> n;
for (int i = 1; i <= n; ++i)
std::cin >> x[i];
for (int i = 1; i <= n; ++i)
std::cin >> y[i];
x[0] = -1e18;
int h = 1, t = 0, ans = 1e18;
for (int i = 1; i <= n; ++i) {
if (y[i] > y[i - 1]) {
q[++t] = {x[i - 1] + 1, y[i] - y[i - 1]};
} else if (y[i] < y[i - 1]) {
int d = y[i - 1] - y[i];
for (; d && h <= t;) {
int w = std::min(q[h].second, d);
d -= w, q[h].second -= w;
ans = std::min(ans, x[i] - 1 - q[h].first);
if (!q[h].second) ++h;
else break;
}
}
}
std::cout << (ans == 1e18 ? -1 : ans) << '\n';
}

int32_t main() {
#ifdef ORZXKR
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
int T = 1;
// std::cin >> T;
while (T--) dickdreamer();
// std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
return 0;
}

[ARC166D] Interval Counts 题解
https://sobaliuziao.github.io/2023/10/28/post/9224f0ca.html
作者
Egg_laying_master
发布于
2023年10月28日
许可协议