链接:https://ac.nowcoder.com/acm/contest/1113/K
来源:牛客网

The cows have reverted to their childhood and are playing a game similar to human hopscotch. Their hopscotch game features a line of N (3 <= N <= 250,000) squares conveniently labeled 1..N that are chalked onto the grass.

Like any good game, this version of hopscotch has prizes! Square i is labeled with some integer monetary value  ViV_iVi​ (-2,000,000,000 <= ViV_iVi​ <= 2,000,000,000). The cows play the game to see who can earn the most money.

The rules are fairly simple:

* A cow starts at square '0' (located just before square 1; it has no monetary value).

* She then executes a potentially empty sequence of jumps toward square N. Each square she lands on can be a maximum of K (2 <= K <= N) squares from its predecessor square (i.e., from square 1, she can jump outbound to squares 2 or 3 if K==2).

* Whenever she wishes, the cow turns around and jumps back towards square 0, stopping when she arrives there. In addition to the restrictions above (including the K limit), two additional restrictions apply:

* She is not allowed to land on any square she touched on her outbound trip (except square 0, of course).

* Except for square 0, the squares she lands on during the return trip must directly precede squares she landed on during the outbound trip (though she might make some larger leaps that skip potential return squares altogether).

She earns an amount of money equal to the sum of the monetary values of all the squares she jumped on. Find the largest amount of cash a cow can earn.

By way of example, consider this six-box cow-hopscotch course where K has the value 3:
Square Num: 0 1 2 3 4 5 6
+---+ +---+ +---+ +---+ +---+ +---+ +---+
|///|--| |--| |--| |--| |--| |--| |
+---+ +---+ +---+ +---+ +---+ +---+ +---+
Value: - 0 1 2 -3 4 5
One (optimal) sequence Bessie could jump (shown with respective bracketed monetary values) is: 1[0], 3[2], 6[5], 5[4], 2[1], 0[0] would yield a monetary total of 0+2+5+4+1+0=12.
If Bessie jumped a sequence beginning with 0, 1, 2, 3, 4, ... then she would be unable to return since she could not legally jump back to an untouched square.

输入描述:

* Line 1: Two space separated integers: N and K
* Lines 2..N+1: Line i+1 contains a single integer: ViV_iVi​

输出描述:

* Line 1: A single line with a single integer that is the maximum amount of money a cow can earn
示例1

输入

复制

6 3
0
1
2
-3
4
5

输出

复制

12

题意:给定一个 n 个格子,每个格子有一个价值,一头牛一开始在 0 格子,每次最多跳 k 个,每当它跳到某个格子上,它就能够获得该格子的价值,并且它随时可以往后跳,但是有两 个限制,一个就是不能再跳已经跳过的格子,再就是必须跳到以前曾经跳过的格子的前一个,直到它跳到 0 格子结束,求它最多能获得多少价值。

析:很容易看出来是一个DP,但是有一个条件特别烦,那就是必须要回来,这个就是对后面的状态有影响,我们必须要消除这个影响,那就是在向前跳的时候就要把已经往后跳的格子也一块算出来,就没有影响了,dp[i] 表示跳到 i 位置,并且 i-1位置是回来要跳的格子,dp[i] = max{dp[j] | i-j >= k && j <= i-2}, 这个状态方程很容易写出来,但是它是不对的,为什么是不对的呢,因为如果 i-k ~ i-2 这些格子中可能它在向前的时候也跳过了,只不过在往后跳的时候没跳过,这样的格子我们没有计算过,再考虑这些格子肯定都是正数,我们不可能去跳负数。状态方程就改变成了 dp[i] = max{dp[j] + sum[i-2]-sum[j] | i-j >= k && j <= i-2},这里 sum[i] 是表示 1~i 这个区间内的所有正数的和。还有一个问题就是 k 太大了,所以直接循环是肯定要超时的,可以使用单调队列来优化, 单调队列中只要比较 dp[j] - sum[j] 就好了,因为sum[i-2]是一个常数,没有啥必要。还要考虑一些特殊情况,比如返回时只直接跳到0,等一些特殊情况。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#include <list>
#include <assert.h>
#include <bitset>
#include <numeric>
#define debug() puts("++++")
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a, b, sizeof a)
#define sz size()
#define be begin()
#define ed end()
#define pu push_up
#define pd push_down
#define cl clear()
#define lowbit(x) -x&x
// #define all 1,n,1
#define FOR(i,n,x) for(int i = (x); i < (n); ++i)
#define freopenr freopen("in.in", "r", stdin)
#define freopenw freopen("out.out", "w", stdout)
using namespace std; typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e17;
const double inf = 1e20;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 250000 + 10;
const int maxm = 1e6 + 10;
const LL mod = 998244353LL;
const int dr[] = {-1, 1, 0, 0, 1, 1, -1, -1};
const int dc[] = {0, 0, 1, -1, 1, -1, 1, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c) {
return r >= 0 && r < n && c >= 0 && c < m;
}
inline int readInt(){ int x; scanf("%d", &x); return x; } LL dp[maxn], sum[maxn];
int a[maxn], q[maxn]; int main(){
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; ++i){
scanf("%d", a + i);
sum[i] = sum[i-1] + (a[i] > 0 ? a[i] : 0);
}
LL ans = sum[min(n, m)];
int front = 0, rear = 0;
q[rear++] = 1;
dp[1] = a[1];
for(int i = 2, j = 0; i <= n; ++i, ++j){
while(front < rear && i - q[front] > m) ++front;
LL val = dp[j] - sum[j];
while(front < rear && val >= dp[q[rear-1]] - sum[q[rear-1]]) --rear;
q[rear++] = j;
int x = q[front];
dp[i] = dp[x] + a[i] + a[i-1] + sum[i-2] - sum[x];
}
for(int i = 1; i <= n; ++i)
ans = max(ans, dp[i] + sum[min(n, i-1+m)] - sum[i]);
printf("%lld\n", ans);
return 0;
}

  

最新文章

  1. Java程序员:工作还是游戏,是该好好衡量一下了
  2. eclipse添加easyExport插件,打开本地文件
  3. 使用dynamic获取类型可变的json对象
  4. Ubuntu 14.04 中安装 VMware10 Tools工具
  5. 加一个 时间戳 TimeStamp 可以解决 重复提交问题 SqlServer
  6. Apache ActiveMQ消息中间件的基本使用
  7. iOS 7 新版微信 URL 不支持跳转 App Store 的解决方案
  8. 说说Xcode4中xib绑定的原理
  9. 解决Virtual Box 安装Mac OS X当出现“hfs: summary table not allowed on FS with block size of 2048”问题
  10. iOS基础 - 数据库CoreData
  11. SpringMVC Hello(IDEA)
  12. Linux.安装phantomjs
  13. Spring Boot学习大全(入门)
  14. Smokeping安装部署
  15. 阿里前CEO卫哲:马云好玩,人工智能泡沫巨大,新零售重在社区
  16. jquery json 格式教程
  17. android studio运行时报错AVD Nexus_5X_API_P is already running解决办法
  18. 自动化CI构建工具
  19. Openstack(十六)实现内外网结构
  20. Android中的自定义注解(反射实现-运行时注解)

热门文章

  1. java_guide_类加载器
  2. tcp与串口透传(select)
  3. 第35课.函数对象分析(&quot;()&quot;重载)
  4. jQuery报错:Uncaught TypeError: _this.attr is not a function
  5. (十四)mybatis 和 spring 整合
  6. Ural 1250 Sea Burial 题解
  7. 序列化,os,sys,hashlib,collections
  8. postman的安装与使用方法介绍
  9. MySQL SELECT语法(四)UNION语法详解
  10. Lua虚拟机中的数据结构与栈