ζ

2021CCPC新疆省赛-E

    题解

题目链接

这题题目非常短,但是非常难以理解。

不论怎么想,这题都只有n^2的算法,但n的规模是2e5,不可能这么解决。但最后又说,a与b的和不大于5000。刚看到题的时候也不是没有注意到这一条,但一直想不明白这个条件有什么用,后面想的内容跟这个条件半点关系都没有,还以为能推出个什么式子直接输出。赛后看了题解才明白:这是在说大于0的数不超过5000个。而这题的解法就是对规模缩减到5000的数据跑的算法。

看了题解后写了一个代码,大致是先将不等于0的a、b都找出来,然后对c的每一项分别枚举不等于0的a、b,看怎样是最大。写完之后见样例过了就交,WA。发现写的时候默认数列从1开始了,而题目中的数列都是从0开始的。这样的话找出不等于0的a、b那一步需要初始化。将代码略加改动之后交上去,直接TLE了。当时我还以为是把从1开始改为从0开始没改干净导致了死循环,后面一分析复杂度,最坏情况的计算次数超过了1e9,难怪超时。

重看题解,得知:将所给式子中a与b的下标相加,就能得知c的下标其实是a与b的和对n取模。题解的代码就是用了这个性质,不用枚举c的每一项,只要通过a、b的下标改变对应的c,其它未经改变的c直接赋为a、b的最大值。

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
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cctype>
using namespace std;
int a[200005], b[200005], c[200005], nexa[200005], nexb[200005];
int main()
{
int n, i, j, maxab = -1, bega = -1, begb = -1, prea = -1, preb = -1;
scanf("%d", &n);
for (i = 0; i <= n; i++)
nexa[i] = nexb[i] = -1;
for (i = 0; i < n; i++)
{
scanf("%d", &a[i]);
if (maxab < a[i])
maxab = a[i];
if (a[i])
{
if (prea < 0)
{
bega = prea = i;
continue;
}
nexa[prea] = i;
prea = i;
}
}
for (i = 0; i < n; i++)
{
scanf("%d", &b[i]);
if (maxab < b[i])
maxab = b[i];
if (b[i])
{
if (preb < 0)
{
begb = preb = i;
continue;
}
nexb[preb] = i;
preb = i;
}
}
for (i = bega; i >= 0; i = nexa[i])
for (j = begb; j >= 0; j = nexb[j])
c[(i + j) % n] = max(c[(i + j) % n], a[i] + b[j]);
for (i = 0; i < n; i++)
printf("%d ", max(maxab, c[i]));
return 0;
}
页阅读量:  ・  站访问量:  ・  站访客数: