Tyvj P1305最大子序和
《进阶指南》单调队列例题
连续子序和一般转化为前缀和维护, 记为sum数组, 连续的子序列[l, r] 的和即为sum[r] - sum[l - 1]
原问题转化为 找到两个位置l, r , 使得sum[l] - sum[r] 最大 且 r - l <= m。
所以单调队列维护一个下标递增, 前缀和也递增的序列, ans不断更新
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 const int sz = 300030; 5 int n, m, ans; 6 int a[sz], sum[sz], p[sz], q[sz]; 7 void work() { 8 int head = 1, tail = 0; 9 q[1] = 0; 10 for(int i = 1; i <= n; i++) { 11 while(head <= tail && p[head] < i - m) head++; 12 ans = max(ans, sum[i] - sum[p[head]]); 13 while(head <= tail && sum[i] <= sum[p[tail]]) tail--; 14 // q[++tail] = sum[i]; 15 p[++tail] = i; 16 // while(p[head] < i - m) head++; 17 } 18 printf("%d", ans); 19 } 20 int main() { 21 scanf("%d%d", &n, &m); 22 for(int i = 1; i <= n; i++) { 23 scanf("%d", &a[i]); 24 sum[i] = a[i] + sum[i-1]; 25 } 26 work(); 27 return 0; 28 }