Description
输入一个长度为n的整数序列,从中找出一段不超过m的连续子序列,使得整个序列的和最大。 例如 1,-3,5,1,-2,3 当m=4时,S=5+1-2+3=7 当m=2或m=3时,S=5+1=6。
Input
第一行两个数n,m(n,m<=300000) 第二行有n个数,要求在n个数找到最大子序和。
Output
一个数,即最大子序和S(S值不超过long long int)。
数据很大,最多允许O(nlogn)的算法,暴力的省省吧;
通读题目,可能比较难以与单调队列扯上联系,但是又想到,子序和的求法,常用方法是前缀和相减,即对于任意k<j<n
序列k-j的和表示为sum[j]-sum[k],这两个数分别是前j个和前k个的数字和;
既然如此,为什么不用队列去维护呢?
考虑到这里我们求序列和,显而易见,对于从j开始的序列,j之前的序列无用,需要pop走,然而后来的队列需要排在后面,我们就用双端队列来维护。
代码如下:
#include<cstdio>
#include<iostream>
#include<algorithm>
#define file
#define maxn 300005
#include<deque>
using namespace std;
struct node{
long long int num,pos;
};
node sum[maxn];
deque<node> k;
long long ans=-999999999;
int main()
{
#ifdef file
freopen("sum.in","r",stdin);
freopen("sum.out","w",stdout);
#endif
int m,n;
cin>>m>>n;
for(int r=1;r<=m;r++)
{
cin>>sum[r].num;
sum[r].pos=r;
sum[r].num+=sum[r-1].num;//存和,利用和之差直接求区间值