TYVJ1305 最大子序和
P1305 最大子序和
时间: 1000ms / 空间: 131072KiB / Java类名: Main
描述
输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大。
例如 1,-3,5,1,-2,3
当m=4时,S=5+1-2+3=7
当m=2或m=3时,S=5+1=6
例如 1,-3,5,1,-2,3
当m=4时,S=5+1-2+3=7
当m=2或m=3时,S=5+1=6
输入格式
第一行两个数n,m
第二行有n个数,要求在n个数找到最大子序和
第二行有n个数,要求在n个数找到最大子序和
输出格式
一个数,数出他们的最大子序和
测试样例1
输入
6 4
1 -3 5 1 -2 3
输出
7
备注
数据范围:
100%满足n,m<=300000
100%满足n,m<=300000
【题解】
给前缀和维护一个单调递增的队列
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #define max(a, b) ((a) > (b) ? (a) : (b)) 6 #define min(a, b) ((a) < (b) ? (a) : (b)) 7 8 inline void swap(int &a, int &b) 9 { 10 int tmp = a;a = b;b = tmp; 11 } 12 13 inline void read(int &x) 14 { 15 x = 0;char ch = getchar(), c = ch; 16 while(ch < '0' || ch > '9')c = ch, ch = getchar(); 17 while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar(); 18 if(c == '-')x = -x; 19 } 20 21 const int INF = 0x3f3f3f3f; 22 const int MAXN = 300000 + 10; 23 24 int n, m, sum[MAXN], q[MAXN], rank[MAXN], head, tail, ans; 25 26 int main() 27 { 28 read(n), read(m); 29 for(register int i = 1;i <= n;++ i) read(sum[i]), sum[i] += sum[i - 1]; 30 head = tail = 1; 31 ans = -INF; 32 for(register int i = 1;i <= n;++ i) 33 { 34 while(i - rank[head] > m)++ head; 35 ans = max(ans, sum[i] - q[head]); 36 while(q[tail] >= sum[i] && tail >= head)-- tail; 37 ++ tail; 38 q[tail] = sum[i], rank[tail] = i; 39 40 } 41 printf("%d", ans); 42 return 0; 43 }