码迷,mamicode.com
首页 > 其他好文 > 详细

洛谷比赛 堕落的Joe

时间:2016-09-17 23:44:21      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:

/*暴力50*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100010
#define ll long long
using namespace std;
ll n,k,f[maxn][110],a[maxn],ans;
ll init(){
    ll x=0,f=1;char s=getchar();
    while(s<0||s>9){if(s==-)f=-1;s=getchar();}
    while(s>=0&&s<=9){x=x*10+s-0;s=getchar();}
    return x*f;
}
int main()
{
    n=init();k=init();
    for(int i=1;i<=n;i++)
        a[i]=init();
    for(int i=1;i<=n;i++)
        for(int j=0;j<=k;j++){
            if(j>0)f[i][j]=max(f[i][j],f[i-1][j-1]+a[i]);
            f[i][0]=max(f[i][0],f[i-1][j]);
            ans=max(ans,f[i][j]);
            ans=max(ans,f[i][0]);
        }
    printf("%lld",ans);
    return 0;
}
/*
暴力的算法不好优化啊QAQ
问了一下长郡中学的shenben学弟
换一个状态 f[i]表示前i个且选了第i个的最大值
n*n的做法是枚举前面的没选的最大的f[j-1]+a[j+1]+a[j+2]+...+a[i]
转移就是 f[i]=max(f[j-1]+a[j+1]+a[j+2]+...+a[i]) 
考虑到选j与i无关 所以只要找max f[j-1]-s[j] 
这里选就选一段 只要保证了i-j<=k就好了
优化嘛 单调队列 里面自然是维护 f[j-1]-s[j] 的最大值
时效性上面说的 i-j<=k
然后 维护下前缀和 
*/
#include<cstdio>
#define maxn 1000010
#define ll long long
using namespace std;
ll n,k,x,a[maxn],f[maxn],q[maxn],head,tail,ans;
ll max(ll a,ll b){
    return a<b?b:a;
}
ll init(){
    ll x=0,f=1;char s=getchar();
    while(s<0||s>9){if(s==-)f=-1;s=getchar();}
    while(s>=0&&s<=9){x=x*10+s-0;s=getchar();}
    return x*f;
}
void ins(ll x){
    while(f[q[tail]-1]-a[q[tail]]<f[x-1]-a[x]&&head<=tail)
        tail--;
    q[++tail]=x;
}
int main()
{
    n=init();k=init();
    for(int i=1;i<=n;i++){
        x=init();
        a[i]=x+a[i-1];
    }
    ins(1);
    for(int i=1;i<=n;i++){
        int p=q[head];
        f[i]=f[p-1]+a[i]-a[p];
        ans=max(ans,f[i]);
        if(i-q[head]==k)head++;
        if(i!=n)ins(i+1);
    }
    printf("%lld\n",ans);
    return 0;
}

 

洛谷比赛 堕落的Joe

标签:

原文地址:http://www.cnblogs.com/yanlifneg/p/5879933.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!