P1725 琪露诺

题目描述

在幻想乡,琪露诺是以笨蛋闻名的冰之妖精。

某一天,琪露诺又在玩速冻青蛙,就是用冰把青蛙瞬间冻起来。但是这只青蛙比以往的要聪明许多,在琪露诺来之前就已经跑到了河的对岸。于是琪露诺决定到河岸去追青蛙。

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

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

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

开始时,琪露诺在编号 000 的格子上,只要她下一步的位置编号大于 NNN 就算到达对岸。

输入格式

第一行三个正整数 N,L,RN, L, RN,L,R

第二行共 N+1N+1N+1 个整数,第 iii 个数表示编号为 i−1i-1i1 的格子的冰冻指数 Ai−1A_{i-1}Ai1

输出格式

一个整数,表示最大冰冻指数。

输入输出样例 #1

输入 #1

5 2 3
0 12 3 11 7 -2

输出 #1

11

说明/提示

对于 60%60\%60% 的数据,N≤104N \le 10^4N104

对于 100%100\%100% 的数据,N≤2×105N \le 2\times 10^5N2×105,$-10^3 \le A_i\le 10^3 $,$1 \le L \le R \le N $。数据保证最终答案不超过 231−12^{31}-12311

solution

动态规划

  • 1 定义公式

    • dp[i] : 走到第 i 格上,最大的和
  • 2 递推关系

    • dp[i] = max(d[j] + a[i])
    •  其中 j 为下一步可以走到该 i 格的格子 j
      
  • 3 结果

    • ans = max(dp[i])
    •  其中 i 为下一步可以走到 > n 的格子
      
  • 优化:

    • 数据量很多,两层循环势必超时。而第二层循环为求区间最大值,可以考虑用单调队列。 第 i 个格子可以由 [i - r, i - l] 这个区间得到, 求该区间的最值

代码

#include "cstdio"
#include "iostream"
#include "vector"
#include "cstring"
#include "queue"
#include "algorithm"
#include "unordered_map"
#include "unordered_set"
#include "list"

/*
 * P1725 琪露诺
 * 题目大意:一列格子编号为 0 到 N (N≤2×10^5),在 i 位置时只移动到区间 [i+L,i+R] 中的任意一格,求移动到 >N 时所走格子和最大
 *
 * 思路:动态规划
 * 1 定义公式
 *      dp[i] : 走到第 i 格上,最大的和
 * 2 递推关系
 *      dp[i] = max(d[j] + a[i])
 *      其中 j 为下一步可以走到该 i 格的格子 j
 * 3 结果
 *      ans = max(dp[i])
 *      其中 i 为下一步可以走到 > n 的格子
 *
 * 优化:
 *      数据量很多,两层循环势必超时。而第二层循环为求区间最大值,可以考虑用单调队列  第 i 个格子可以由  
 *      [i - r, i - l] 这个区间得到, 求该区间的最值
 *
 */

using namespace std;
const int N = 2e5 + 5;

int dp[N], a[N], ans = -1e9, n, r, l;
list<int> q;

int main() {
    cin >> n >> l >> r;

    int m = r - l + 1;
    for (int i = 0; i <= n; i++) cin >> a[i], dp[i] = -1e9;

    dp[0] = 0;
    for (int i = l; i <= n; i++) {
        while (!q.empty() && dp[q.back()] <= dp[i - l]) q.pop_back();

        q.push_back(i - l);
        if (i - l - q.front() >= m) q.pop_front();
        dp[i] = dp[q.front()] + a[i];
        if (i + r > n) ans = max(ans, dp[i]);
    }

    cout << ans << endl;
    return 0;
}

结果

在这里插入图片描述

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐