CH1201 最大子序和

http://contest-hunter.org:83/contest/0x10%E3%80%8C%E5%9F%BA%E6%9C%AC%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E3%80%8D%E4%BE%8B%E9%A2%98/1201%20%E6%9C%80%E5%A4%A7%E5%AD%90%E5%BA%8F%E5%92%8C

题目

输入一个长度为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

一个数,数出他们的最大子序和

题解

贪心,$Ans[i]=S[i]-min{S[i..i-m]}$,可以用滑动窗口

还需要考虑开头什么都不减,可以用特殊元素

AC代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#define REP(r,x,y) for(register int r=(x); r<(y); r++)
#define REPE(r,x,y) for(register int r=(x); r<=(y); r++)
#ifdef sahdsg
#define DBG(...) printf(__VA_ARGS__)
#else
#define DBG(...) (void)(0)
#endif

typedef long long LL;
using namespace std;

char ch; int si;
template <class T>
inline void read(T &k) {
	k=0; si=1; do ch=getchar(); while(!isdigit(ch) && ch!='-' );
	if(ch=='-') {si=-1,ch=getchar();} while(isdigit(ch)) {k=k*10+ch-'0'; ch=getchar();}
	k*=si;
}

#define MAXN 1000007
LL arr[MAXN];
LL aw[MAXN], al=0, ar=1;
int main() {
#ifdef sahdsg
	freopen("in.txt", "r", stdin);
#endif
    int n,m;
    read(n); read(m);
    LL ans=-0x3f3f3f3f3f3f3f3fLL;
    REPE(i,1,n) {
        read(arr[i]);
//        if(i>1) arr[i]+=arr[i-1];
    }
    aw[0]=0;
    REPE(i,1,n) {
        while(ar>al && arr[i]<arr[aw[ar-1]]) ar--;
        aw[ar++]=i;
        while(ar>al && i-aw[al]>m) al++;
        printf("%lld
", arr[aw[al]]);
    }
	return 0;
}
原文地址:https://www.cnblogs.com/sahdsg/p/10785913.html