HDU3415 Max Sum of Max-K-sub-sequence (DP+单调队列)

题目链接:

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

题意:

给定一个长度为n的环,求其中一个长度小于等于k的区间,使其和最大,输出最大和,区间的左右端点

分析:

直接想到暴力 dp[i]= sum[i] - sum[i-k+1+j]  (0<=j<=k);

但是很明显暴力会超时,就想到用单点队列来维护,一个sum数组,

使其sum尽量小的在前面.处理的时候要将环展开,sum存的是前缀和。

代码如下:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;

const int maxn = 100010;

int a[maxn*2],sum[maxn*2];

int main()
{
    int t,n,k;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&k);
        memset(sum,0,sizeof(sum));
        for(int i=1;i<=n;i++){
            scanf("%d",a+i);
            sum[i]=sum[i-1]+a[i];
            a[i+n]=a[i];
        }
        for(int i=n+1;i<=2*n;i++)
            sum[i]=sum[i-1]+a[i];
        deque<int >Q;
        int ans = -1000000000,st=0,ed=0;
        for(int i=1;i<=n+k-1;i++){
            while(!Q.empty()&&sum[i-1]<sum[Q.back()])//保持队列的单调性
                Q.pop_back();
            while(!Q.empty()&&Q.front()<i-k)//超过k的长度则消除队列前面的元素
                Q.pop_front();
            Q.push_back(i-1);
            if(sum[i]-sum[Q.front()]>ans){
                ans=sum[i]-sum[Q.front()];
                st=Q.front()+1;
                ed=i;
            }
        }
        if(ed>n) ed-=n;
        printf("%d %d %d\n",ans,st,ed);
    }
    return 0;
}
时间: 2024-08-03 16:52:35

HDU3415 Max Sum of Max-K-sub-sequence (DP+单调队列)的相关文章

POJ 3017 Cut the Sequence (单调队列优化DP)

POJ 3017 Cut the Sequence (单调队列优化DP) ACM 题目地址: POJ 3017 Cut the Sequence 题意: 将一个由N个数组成的序列划分成若干段,要求每段数字的和不超过M,求[每段的最大值]的和 的最小的划分方法,输出这个最小的和. 分析: 方程是:dp[i] = min(dp[j]+maxsum[j+1][i]) 但复杂度n*n太高,需要优化. 可以用单调队列+BST优化,其实只需要维护每一段的最大值. 看了这篇题解的:http://blog.cs

HDU 1003 Max Sum &amp;&amp; HDU 1231 最大连续子序列 (DP)

Max Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 154155    Accepted Submission(s): 35958 Problem Description Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max su

Max Sum Plus Plus HDU - 1024 基础dp 二维变一维的过程,有点难想

/* dp[i][j]=max(dp[i][j-1]+a[j],max(dp[i-1][k])+a[j]) (0<k<j) dp[i][j-1]+a[j]表示的是前j-1分成i组,第j个必须放在前一组里面. max( dp[i-1][k] ) + a[j] )表示的前(0<k<j)分成i-1组,第j个单独分成一组. */ #include <iostream> #include <cstdio> #include <cstring> #inclu

poj 3017 Cut the Sequence(单调队列优化 )

题目链接:http://poj.org/problem?id=3017 题意:给你一个长度为n的数列,要求把这个数列划分为任意块,每块的元素和小于m,使得所有块的最大值的和最小 分析:这题很快就能想到一个DP方程 f[ i ]=min{ f[ j ] +max{ a[ k ] }}( b[ i ]<j<i,j<k<=i)     b[ i ]到 i的和大于m 这个方程的复杂度是O(n^2),明显要超时的(怎么discuss都说数据弱呢= =) 然后是优化了,首先当然是要优化一个最大

HDU 6047 Maximum Sequence (贪心+单调队列)

题意:给定一个序列,让你构造出一个序列,满足条件,且最大.条件是 选取一个ai <= max{a[b[j], j]-j} 析:贪心,贪心策略就是先尽量产生大的,所以就是对于B序列尽量从头开始,由于数据比较大,采用桶排序,然后维护一个单调队列,使得最头上最大. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #i

HDOJ 3415 Max Sum of Max-K-sub-sequence(单调队列)

因为是circle sequence,可以在序列最后+序列前n项(或前k项);利用前缀和思想,预处理出前i个数的和为sum[i],则i~j的和就为sum[j]-sum[i-1],对于每个j,取最小的sum[i-1],这就转成一道单调队列了,维护k个数的最小值. ---------------------------------------------------------------------------------- #include<cstdio> #include<deque&

HDU 1003 Max Sum(dp,最大连续子序列和)

Max Sum Problem Description Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14. Input The first line of the input

HDU 1003.Max Sum【最大连续子序列和】【8月14】

Max Sum Problem Description Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14. Input The first line of the input

POJ 1003 Max Sum

Max Sum Problem Description Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14. Input The first line of the input