1. 程式人生 > >【練習】最大子序和

【練習】最大子序和

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 }