Cow Hopscotch (单调队列 + DP)
链接: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
题意:给定一个 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;
}
Cow Hopscotch (单调队列 + DP)的更多相关文章
- POJ 3017 单调队列dp
Cut the Sequence Time Limit: 2000MS Memory Limit: 131072K Total Submissions: 8764 Accepted: 2576 ...
- [TyvjP1313] [NOIP2010初赛]烽火传递(单调队列 + DP)
传送门 就是个单调队列+DP嘛. ——代码 #include <cstdio> ; , t = , ans = ~( << ); int q[MAXN], a[MAXN], f ...
- zstu 4237 马里奥的求救——(单调队列DP)
题目链接:http://oj.acm.zstu.edu.cn/JudgeOnline/problem.php?id=4237 这题可以转化为每次可以走g~d+x步,求最大分数,且最大分数的步数最少. ...
- 1304F2 - Animal Observation (hard version) 线段树or单调队列 +DP
1304F2 - Animal Observation (hard version) 线段树or单调队列 +DP 题意 用摄像机观察动物,有两个摄像机,一个可以放在奇数天,一个可以放在偶数天.摄像机在 ...
- BZOJ 5281--[Usaco2018 Open]Talent Show(分数规划&单调队列&DP)
5281: [Usaco2018 Open]Talent Show Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 79 Solved: 58[Sub ...
- vijos P1243 生产产品(单调队列+DP)
P1243生产产品 描述 在经过一段时间的经营后,dd_engi的OI商店不满足于从别的供货商那里购买产 品放上货架,而要开始自己生产产品了!产品的生产需要M个步骤,每一个步骤都可以在N台机器 ...
- POJ 1821 单调队列+dp
题目大意:有K个工人,有n个墙,现在要给墙涂色.然后每个工人坐在Si上,他能刷的最大范围是Li,且必须是一个连续子区间,而且必须过Si,他刷完后能获得Pi钱 思路:定义dp[i][j]表示前i个人,涂 ...
- codeforces 1077F2. Pictures with Kittens (hard version)单调队列+dp
被队友催着上(xun)分(lian),div3挑战一场蓝,大号给基佬紫了,结果从D开始他开始疯狂教我做人??表演如何AKdiv3???? 比赛场上:A 2 分钟,B题蜜汁乱计数,结果想得绕进去了20多 ...
- 【LOJ#10180】烽火传递 单调队列+dp
题目大意:给定一个 N 个非负整数数组成的序列,每个点有一个贡献值,现选出其中若干数,使得每连续的 K 个数中至少有一个数被选,要求选出的数贡献值最小. 题解:设 \(dp[i]\) 表示考虑了序列前 ...
随机推荐
- js中函数总结(1)
8.1函数定义js的函数可以嵌套在其他函数的定义中,这样它们就可以访问它们被定义时所处的作用域中的任何变量.意味着js函数构成了一个闭包:function name(){} 特殊的:函数表达式有时定义 ...
- java核心技术(第四章)对象与类
4.1 面向对象程序设计概述 每个对象包含对用户公开的特定功能部分和隐藏的实现部分. 4.1.1类 由类构造对象的过程称为创建类的实例. 封装(数据隐藏)是与对象有关的.从形式上看,封装不过是将数据和 ...
- SpringBoot 使用WebSocket打造在线聊天室
教程: https://www.jianshu.com/p/55cfc9fcb69e https://wallimn.iteye.com/blog/2425666 关于websocket基础普及见:h ...
- Hadoop和Spark的Shuffer过程对比解析
Hadoop Shuffer Hadoop 的shuffer主要分为两个阶段:Map.Reduce. Map-Shuffer: 这个阶段发生在map阶段之后,数据写入内存之前,在数据写入内存的过程就已 ...
- 【jmeter测试范例】001——TCP测试
1.打开Jmeter(或者运行NewDriver.java启动Jmeter) 2.新建一个测试计划 ······ 3.新建线程组 4.设置线程组的参数 1.线程的数量 2.要在多久内完成,即每个请求发 ...
- Idea中Smart Tomcat插件启动报NullPointerException问题
如果你跟我一样用的是Idea Community社区版的话,也一定会遇到用Smart Tomcat插件启动报错的问题: 这个问题网上搜了一圈,大家好像也都遇到过了,不过也都没有找到原因和给出解决方案. ...
- 适合新手的160个creakme(四)
这题没有什么特殊字符串,Delphi写的,使用DeDeDark分析一下,找到几个特殊的事件 一个是KeyUp 一个是chkcode 还有就是中间区域的单击或是双击事件 直接跟进去这几个函数,然后找比较 ...
- 【Trie】The XOR Largest Pair
[题目链接] https://loj.ac/problem/10050 [题意] 给出n个数,其中取出两个数来,让其异或值最大. [题解] 经典的01字典树问题. 首先需要把01字典树建出来. 然后对 ...
- Spring与Web框架(例如Spring MVC)漫谈——关于Spring对于多个Web框架的支持
在看Spring MVC的官方文档时,最后一章是关于Spring对于其它Web框架的支持(如JSF,Apache Struts 2.x,Tapestry 5.x),当然Spring自己的MVC框架Sp ...
- docker 入门3 - 服务 【翻译】
入门,第 3 部分:服务 先决条件 安装 Docker 版本 1.13 或更高版本. 获取 Docker Compose.在适用于 Mac 和 Docker 桌面的 Windows 上,它已预安装,因 ...