zoukankan      html  css  js  c++  java
  • jzoj 3128. 【WinterCamp 2013】跳格子

    Description

    奶牛们正在回味童年,玩一个类似跳格子的游戏,在这个游戏里,奶牛们在草地上画了一行N个格子,(3 <=N <= 250,000),编号为1…N。
    就像任何一个好游戏一样,这样的跳格子游戏也有奖励!第i个格子标有一个数字V_i(-2,000,000,000 <=V_i <= 2,000,000,000)表示这个格子的钱。奶牛们想看看最后谁能得到最多的钱。
    规则很简单:

    • 每个奶牛从0号格子出发。(0号格子在1号之前,那里没钱)
    • 她向N号格子进行一系列的跳跃(也可以不跳),每次她跳到的格子最多可以和前一个落脚的格子差K格(1 <= K <= N)(比方说,当前在1号格,K=2, 可以跳到2号和3号格子)
    • 在任何时候,她都可以选择回头往0号格子跳,直到跳到0号格子。
      另外,除了以上规则之外,回头跳的时候还有两条规则:
    • 不可以跳到之前停留的格子。
    • 除了0号格子之外,她在回来的时候,停留的格子必须是恰巧过去的时候停留的某个格子的前一格(当然,也可以跳过某些过去时候停留的格子)。简单点说,如果i号格子是回来停留的格子,i+1号就必须是过去停留的格子,但如果i+1号格子是过去停留的格子,i号格子不一定要是回来停留的格子。
      她得到的钱就是所有停留过的格子中的数字的和,请你求出最多奶牛可以得到的钱数。

    Input

    • 第1行 1: 两个用空格隔开的整数: N 和 K

    • 第2到N+1行: 第i+1行有一个整数: V_i

    Output

    • 第一行: 一个单个的整数表示最大的钱数是多少。

    Sample Input

    5 2
    0
    1
    2
    -3
    4

    Sample Output

    4

    Data Constraint

    Hint

    【样例解释】
    在样例中,K=2,一行5个格子,钱数分别为0、1、2、-3、4
    一个合法的序列Bessie可以选择的是0[0], 1[0], 3[2], 2[1], 0[0]。(括号里的数表示钱数)这样,可以得到的钱数为0+0+2+1+0 = 3。
    如果Bessie选择一个序列开头为0, 1, 2, 3, …,那么她就没办法跳回去了,因为她没办法再跳到一个之前没跳过的格子。
    序列0[0], 2[1], 4[-3], 5[4], 3[2], 1[0], 0[0]是最大化钱数的序列之一,最后的钱数为(0+1-3+4+2+0 = 4)。还有一种可能的最大化钱数的序列是: 0[0] 2[1] 4[-3] 5[4] 3[2] 1[0] 0[0]。

    Solution

    这题我们要求的是最大值,我们可以想到DP。
    设f[i]表示过去到i点然后回来是走了i-1点,
    设sum[i]表示1~i中的正数的和,那么转移方程即为:
    fi=fj+vi+vi1+sumi2sumj(iKj&lt;i1)f_{i}=f_{j}+v_{i}+v_{i-1}+sum_{i-2}-sum_{j} (i-Kleq j&lt;i-1)
    我们发现时间过不了,然后用斜率优化即可。
    答案为max(fj+sumi+K1sumi)max(f_{j}+sum_{i+K-1}-sum_{i})

    Code

    #include<cstdio>
    #include<algorithm>
    #define N 250010
    #define db double
    #define ll long long
    using namespace std;
    int n,K,v[N],l=0,len=1,g[N];
    ll ans,sum[N],f[N];
    
    inline int read()
    {
    	int x=0,f=0; char c=getchar();
    	while (c<'0' || c>'9') f=(c=='-') ? 1:f,c=getchar();
    	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return f ? -x:x;
    }
    
    int main()
    {
    	freopen("jump.in","r",stdin);
    //	freopen("jump.out","w",stdout);
    	n=read(),K=read();
    	for (int i=1,x;i<=n;i++)
    		v[i]=read(),sum[i]=sum[i-1]+max(0,v[i]);
    	ans=max(0ll,sum[K]);
    	for (int i=1;i<=n;i++)
    	{
    		while (l<len && g[l]+K<i) l++;
    		f[i]=f[g[l]]+v[i]+v[i-1]+sum[i-2]-sum[g[l]];
    		ans=max(ans,f[i]+sum[min(i+K,n)]-sum[i]);
    		while (l<len && f[i]-sum[i]>f[g[len]]-sum[g[len]]) len--;
    		g[++len]=i;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
    转载需注明出处。
  • 相关阅读:
    javascript解决方案插件
    vscode前端快速开发插件
    html5新增语义标签
    vscode快捷键大全
    vscode/sublime前端开发快捷键
    vscode自动缩进快捷键
    Android平台OpenGL ES/Assimp/OpenCV/GLM集成说明
    将AOSP源码导入到Android Studio进行查看
    Android OTA升级
    Android构建系统
  • 原文地址:https://www.cnblogs.com/jz929/p/11817532.html
Copyright © 2011-2022 走看看