跳棋



#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
long long f[1000002];
bool vis[1000002];
struct p{
	long long x;
	int id;
	bool operator <(const p &a) const{
	return x>a.x;}
};
priority_queue<p>q;
int n,l,r;
int main(){
	cin>>n>>l>>r;
	for(int i=1;i<=n;i++)
	scanf("%d",&f[i]);
	p now;
	now.id=0;
	now.x=0;
	vis[0]=1;
	q.push(now);
	for(int i=l+1;i<=n;i++)
	{
	     now=q.top();
	    while(q.size()>1&&now.id+r+1<i) q.pop(),now=q.top();
	    if(q.size()!=1||now.id+r+1>=i) 
		{
		vis[i]=1;
		f[i]+=now.x;
		}
	    if(vis[i-l])
	    {
		now.id=i-l;
	    now.x=f[i-l];
		}
	    q.push(now);
		}
    if(vis[n]) printf("%lld",f[n]);
    else printf("-1");
	return 0;
}

跳棋

Description

小明迷恋上了一个新的跳棋游戏,游戏规则如下:棋盘是一排从0开始,顺序编号的格子, 游戏开始时你位于0号格子,你每次只能往编号大的格子跳,而且你每次至少需要跳过L个格 子,至多只能跳过R个格子。每个格子都有一个给定的伤害值,显然你希望得到的伤害值越 少越好。
你能告诉小明他当他跳到最后一个格子时受到的累积伤害值最小为多少吗? 如果无论如何小明都无法跳到最后一个格子,这个时候你需要输出"-1"。 注:从i号格子跳过x个格子表示从i号格子跳到第i+x+1号格子。 

Input

第一行有三个整数n、L和R,n表示格子的编号从0到n。L和R表示最少需要跳过的格子数和最多能够跳过的格子数。
第二行有n个正整数,两个数字间用空格隔开,表示每个格子的伤害值。

Output

仅有一个整数,表示受到的最小伤害值,保证结果小于 maxlongint。

Sample Input

10 2 6
1 3 5 7 9 2 4 6 8 10

Sample Output

12

Sample Explanation

Hint

50%的数据:1 ≤ n ≤ 1000;
65%的数据:1 ≤ n ≤ 10000;
100%的数据:1 ≤ n ≤ 1000000,1 ≤ L ≤ R ≤ n, 其中有15%的数据:1 ≤ n ≤ 1000000,1 ≤ L ≤ R ≤ 10 。

好吧,这是我第一篇博文,这题其实80分不难,应该是很简单,f[i]=f[i]+min{f[j]|j是i能达到的}
但是有个坑,好吧我就被坑了,就是不清楚终点是否能到达,即是否输出-1。
好吧,说说满分算法,一看到一个L和R,不能想到这是类似于滑动窗口;
我们可以用堆或者单调队列维护,好吧,我用的是单调队列,比较简单……
话不多说,看代码吧。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值