最近的做题小结(三)

洛谷 1 月月赛 III

B. 多边形

大致题意:给定一个长度为 的数组 ,对于 ,判断能否恰好从 中选取 个数拼成一个面积严格大于 的多边形。

思路:容易观察到一组数能组成一个 边形的充要条件是任意一条边都小于剩余 条边的和,亦即满足最小的 个数的和比最大的数大就可以。当 作为最长边时,很容易想到其余 条边要取比 小的最大的 个数,故 需要排序+前缀和维护区间。且若

成立,则对于任意的

一定成立,此时将 区间标记为 true

由于数组已排序,区间和具有单调性,故 可通过二分查找求得,区间标记可通过差分单点维护首尾的状态,最后再将 遍历一遍复原标记状态即可。

代码

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

using namespace std;

int read() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return x * f;
}

signed main() {
int n = read();
vector<int> a(n);
for (int i = 0; i < n; i++) {
a[i] = read();
}
sort(a.begin(), a.end());
vector<int> pre_sum(n + 1);
for (int i = 0; i < n; i++) {
pre_sum[i + 1] = pre_sum[i] + a[i];
}
vector<int> diff(n + 2, 0);

for (int i = 2; i < n; i++) {
int l = 3, r = i + 1, k_min = -1;
while (l <= r) {
int mid = (l + r) >> 1;
int tot = pre_sum[i + 1] - pre_sum[i - mid + 1];
if (tot > 2 * a[i]) {
k_min = mid;
r = mid - 1;
} else {
l = mid + 1;
}
}
if (k_min != -1) {
diff[k_min]++;
diff[i + 2]--;
}
}
int cnt = 0;
for (int k = 3; k <= n; k++) {
cnt += diff[k];
if (cnt > 0) {
cout << k << " ";
}
}
cout << endl;
return 0;
}

整体复杂度

思考

有没有简单一点的做法?暴力会不会超时?

如果我们不使用二分查找,对于每个 ,都判断是否存在一个 ,使得

成立,这样将十分简便,但这样逻辑似乎是 ²

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bool check(int k, int n) {
for (int i = k; i <= n; i++) {
if (s[i - 1] - s[i - k] > a[i]) {
return 1;
}
}
return 0;
}

signed main() {
for (int k = 3; k <= n; k++) {
if (check(k, n)) {
cout << k << endl;
}
}
}

事实并非如此。虽然其表面上看是两重循环,但实际上会有很大一部分被剪枝掉,也就是说当 很大的时候,check 函数一般来说很快就会返回 ,内层循环不会到 的级别。

证明很容易,我们考虑 check 函数能执行满的最坏情况,令 ,在这种情况下,如果

仍成立,则 的值至少要为

可以看到 其实就是一个二阶的斐波那契数列,呈指数级增长,证明显然。

由于题中的 最大值为 ,故内层循环的最大量级为 是一个常数,整体复杂度 ,并不会超时。

拓展

最坏情况下, 增长速率上限?

相当于求 阶斐波那契数列特征根中最大值。对于 阶斐波那契数列,其特征方程为

时,右侧为等比数列求和

整理,得

由于 ,故

事实上,其收敛到 ,且为指数级快速趋近,具体证明读者可自行探索。

C. 传送

(未完待续……)


最近的做题小结(三)
https://lngym.top/算法竞赛/最近的做题小结(三)/
作者
lngym
发布于
2026年1月19日
许可协议