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; }
|