HDU 3415 Max Sum of Max-K-sub-sequence 单调队列题解

本题又是一题单调队列题解。

技巧就是需要计算好前n项和Sn = a1 + a2 + ... an

这样方便处理。

记录一条单调队列,其意义是: q(head), q(head+1), ...q(tail)

其中头q(head)代表当前最佳解的起点

这样我们只需要在求某点为结尾的S[i] - S[q(head)就得到当前最佳值。

了解了单调数列,知道其中的记录意义,那么这道题就没有难度了。我也是了解这些信息之后就自己敲出代码的。

不过有些细节没写好也让我WA了几次。

最近少刷水题,而一直都是每天一个新的算法,也学了不少算法了。

#include <stdio.h>
#include <limits.h>

const int MAX_N = 100001;
int N, K;
int arr[MAX_N];
int S[MAX_N<<1];
int qu[MAX_N<<1];
int val, sta, end;

void getMaxK()
{

	int tail = 0, head = 0;
	qu[0] = 0;	//记录S数组的下标
	int len = N+K;
	val = INT_MIN;
	for (int i = 1; i < len; i++)
	{
		while (tail >= head && S[i-1] <= S[qu[tail]]) tail--;
		while (tail >= head && qu[head] < i - K) head++;//不能漏了tail>=head
		qu[++tail] = i-1;//这句可以放前一句前面,那么就可以不用tail>=head判断了

		int sum = S[i] - S[qu[head]];
		if (sum > val || sum == val && qu[head]+1==sta && i-qu[head]<end-sta+1)
		{
			val = sum;
			sta = qu[head]+1;
			end = i;
		}
	}
}

int main()
{
	int T;
	scanf("%d", &T);
	S[0] = 0;
	while (T--)
	{
		scanf("%d %d", &N, &K);
		for (int i = 1; i <= N; i++)
		{
			scanf("%d", &arr[i]);
			S[i] = arr[i] + S[i-1];
		}
		for (int i = 1; i < K; i++)
		{
			S[i+N] = arr[i] + S[i+N-1];
		}
		getMaxK();
		if (end > N) end = end % N;
		printf("%d %d %d\n", val, sta, end);
	}
	return 0;
}

HDU 3415 Max Sum of Max-K-sub-sequence 单调队列题解,布布扣,bubuko.com

时间: 2024-12-23 13:55:19

HDU 3415 Max Sum of Max-K-sub-sequence 单调队列题解的相关文章

HDU 4193 Non-negative Partial Sums(想法题,单调队列)

HDU 4193 题意:给n个数字组成的序列(n <= 10^6),求该序列的循环同构序列中,有多少个序列的任意前i项和均大于或等于0. 思路: 这题看到数据规模觉得只能用最多O(nlogn)的算法,然后想到了之前刚做过的有关最小表示法的题,但还没证明出一个做这题有效的算法出来. 后来看过题解,发现用的最多的方法是单调队列,然而我对这个知识点知之甚少orz /*科普君:from单调队列 单调队列是指:队列中元素之间的关系具有单调性,而且,队首和队尾都可以进行出队操作,只有队尾可以进行入队操作.

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

hdu3415——Max Sum of Max-K-sub-sequence

Max Sum of Max-K-sub-sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 6130    Accepted Submission(s): 2234 Problem Description Given a circle sequence A[1],A[2],A[3]......A[n]. Circle s

【HDU 1081】To The Max(求子矩阵元素和)

题目应该很容易看懂,是为了求一个矩阵之内最大的一个子矩阵的和. 子矩阵的和表示的是该矩阵内所有元素的和. 方法引入: 首先当然十分容易的可以想到一维求子段的和. 假设数组为a[110]; int sum = 0, MAX = 0,n; for (int i = 0; i < n; i++) { if (sum < 0) sum = 0; sum += a[i]; if (sum>MAX) MAX = sum; } 其中a[i]表示的是你所要积的范围大小,因为是一维,所以我们要积的是每一个

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

hdu 3415 单调队列

Max Sum of Max-K-sub-sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5690    Accepted Submission(s): 2059 Problem Description Given a circle sequence A[1],A[2],A[3]......A[n]. Circle s

HDU 3415 Max Sum of Max-K-sub-sequence 最长K子段和

链接:http://acm.hdu.edu.cn/showproblem.php?pid=3415 题意:给出一个数环,要找出其中9长度小于等于K的和最大的子段. 思路:不能采用最暴力的枚举,题目的数据量是10^5,O(N^2)的枚举回去超时,本题采用的很巧妙的DP做法,是用单调队列优化的DP. 运用的是STL的deque,从i:1~a找到以其中以i为尾的符合条件的子段,并将i本身放入双向队列,所有i从队列后放入,保证了队列的单调性. 代码: #include <iostream> #incl

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

题目链接:hdu 3415 Max Sum of Max-K-sub-sequence 题意: 给你一串形成环的数,让你找一段长度不大于k的子段使得和最大. 题解: 我们先把头和尾拼起来,令前i个数的和为sum[i]. 然后问题变成了求一个max{sum[i]-sum[j]}(i-k<j<i) 意思就是对于每一个sum[i],我们只需要找一个满足条件的最小的sum[j],然后我们就可以用一个单调队列来维护. 1 #include<bits/stdc++.h> 2 #define F