1. 1. 题目
    1. 1.1. 琪露诺
      1. 1.1.1. 题目描述
  2. 2. 题解
  3. 3. 代码

题目

琪露诺

题目描述

小河可以看作一列格子依次编号为 00NN,琪露诺只能从编号小的格子移动到编号大的格子。而且琪露诺按照一种特殊的方式进行移动,当她在格子 ii 时,她只移动到区间 [i+L,i+R][i+L,i+R] 中的任意一格。你问为什么她这么移动,这还不简单,因为她是笨蛋啊。

每一个格子都有一个冰冻指数 AiA_i,编号为 00 的格子冰冻指数为 00。当琪露诺停留在那一格时就可以得到那一格的冰冻指数 AiA_i。琪露诺希望能够在到达对岸时,获取最大的冰冻指数,这样她才能狠狠地教训那只青蛙。

但是由于她实在是太笨了,所以她决定拜托你帮它决定怎样前进。

开始时,琪露诺在编号 00 的格子上,只要她下一步的位置编号大于 NN 就算到达对岸。
N2×105N \le 2\times 10^5

题解

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