【DP+单调队列】 hdu3415 Max Sum of Max-K-sub-sequence

来源:互联网 发布:b站雪河炮太捏脸数据 编辑:程序博客网 时间:2024/06/03 01:44

Max Sum of Max-K-sub-sequence

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3415

题意:一个长度为n包含正负整数的数环,即第1个的左边是第n个。从中选一个不超过k的序列,使得序列和最大,最大值相同选开始点最小的,开始点相同选长度最小的。

题解:不难看出动态方程为dp[i]=max{sum[i]-sum[j]}(i-k<j<i) ,dp[i]表示以i结尾的最大值,sum表示从1到i的序列和,枚举的话要0(n^2),明显要超时,这时可以使用单调队列维护一个非递减队列,因为对于确定的i,要使和最大就得使sum[j]最小,而单调队列的队头就是能选的j中sum[j]最小的。

代码:

#include<cstdio>#include<cstring>using namespace std;#define MAX 100005#define inf 0xfffffint summ[MAX<<1];//summ[i]代表1到i的和int value[MAX<<1];//value[i]代表第i个值int q[MAX<<1];//模拟队列,存放选取位置的下标int front,back;//队列头尾int main(){    int t,n,m,k,cnt;    scanf("%d",&t);    for(;t--;)    {        summ[0]=0;        scanf("%d%d",&n,&k);        for(int i=1;i<=n;++i)        {            scanf("%d",value+i);            summ[i]=value[i]+summ[i-1];        }        for(int i=n+1;i<=n+k;++i) summ[i]=summ[i-1]+value[i-n];        m=n+k-1;        front=back=1;        int ans=-inf,st,en;        //dp[i]=max{summ[i]-summ[j]}(i-k<j<i) dp[i]为以第i个结尾的最大值        //对于每个i要使最大值最大,就得选summ[j]最小的        for(int i=1;i<=m;++i)        {            for(;front<back&&summ[i-1]<summ[q[back-1]];--back);//维护单调非递减序列            q[back++]=i-1;            for(;front<back&&i-q[front]>k;++front);//将队头超出范围的舍弃            if(summ[i]-summ[q[front]]>ans)            {                ans=summ[i]-summ[q[front]];                st=q[front]+1;                en=i;            }        }        if(en>n) en%=n;        printf("%d %d %d\n",ans,st,en);    }    return 0;}

来源:http://blog.csdn.net/acm_ted/article/details/7909178

原创粉丝点击