题目
琪露诺
题目描述
小河可以看作一列格子依次编号为 0 到 N,琪露诺只能从编号小的格子移动到编号大的格子。而且琪露诺按照一种特殊的方式进行移动,当她在格子 i 时,她只移动到区间 [i+L,i+R] 中的任意一格。你问为什么她这么移动,这还不简单,因为她是笨蛋啊。
每一个格子都有一个冰冻指数 Ai,编号为 0 的格子冰冻指数为 0。当琪露诺停留在那一格时就可以得到那一格的冰冻指数 Ai。琪露诺希望能够在到达对岸时,获取最大的冰冻指数,这样她才能狠狠地教训那只青蛙。
但是由于她实在是太笨了,所以她决定拜托你帮它决定怎样前进。
开始时,琪露诺在编号 0 的格子上,只要她下一步的位置编号大于 N 就算到达对岸。
N≤2×105
题解
设f[i]表示到达i时候能获得的最大的价值
转移也很容易想到,就是会T
想一想,可以用单调队列优化dp
单调队列维护i-R到i-L区间内的f的最大值
(单调队列写的时候几个易错点:
1.头尾处理的时候用的是while
2.想明白单调队列里存的是下标)
!!!别忘了初始化!就像这组数据,有的点是走不到的
6 2 2 0 1 -1 1 -1 1 -1
应该为-3
代码
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
| #include<bits/stdc++.h> const int N = 2e5 + 10; using namespace std; int read() { int f = 1, x = 0; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return f * x; }
int n, L, R; int a[N], f[N];
int qwq[N], h = 1, t = 0;
int main() { n = read(), L = read(), R = read(); n ++; for(int i = 1;i <= n;i++) f[i] = -0x3f3f3f3f; f[1] = 0; for(int i = 1;i <= n;i++) { a[i] = read(); } int ans = -0x3f3f3f3f; for(int i = 1;i <= n;i++) { if(i - L >= 1) { while(t >= h && f[i - L] >= f[qwq[t]]) t--; qwq[++t] = i - L; while(qwq[h] < i - R) h++; f[i] = f[qwq[h]] + a[i]; }
if(i + R > n) ans = max(ans, f[i]); } printf("%d", ans); return 0; }
|