1800. Sequence
Constraints
Time Limit: 1 secs, Memory Limit: 32 MB
Description
Given a sequence S of n numbers and two length bounds L and U.
Your task is to write a program to find a segment S[i], S[i+1], …, S[j] with minimum sum over all segments of S with length at least L and at most U.
Input
The input consists of multiple datasets. The end of the input is indicated by a line containing a zero.
The format of each dataset is as follows.
n
L U
S1 S2 … Sn
Here, all data items are integers. n is the length of the sequence (N≤32767). L and Uare two length bounds where L≤U. S1, S2, …, Sn are the sequence of n numbers.
Output
For each dataset, output the minimum sum of segment, in a separate line.
Sample Input
9 2 8 -3 2 -2 5 -4 1 -2 3 1 0
Sample Output
-5
Hint
the segment is -4 1 -2.
建立一棵线段树存储前缀和的最大值,注意从 0 开始
枚举区间右端点 i,查询 max(0,i-u) 到 i 范围内前缀和的最大值,用 i 处的前缀和减去它就是所求的最小值
其实一开始还想歪用 O(nlogn) 的分治法求最小连续子段和,枚举区间左右端点……这样就成了 O(n^2) 了(
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #define rep(i,l,r) for(int i = l; i <= r; i++) 6 #define clr(x,y) memset(x,y,sizeof(x)) 7 #define travel(x) for(Edge *p = last[x]; p; p = p -> pre) 8 using namespace std; 9 const int maxn = 32800; 10 inline int read(){ 11 int ans = 0, f = 1; char c = getchar(); 12 for(; !isdigit(c); c = getchar()) if (c == '-') f = -1; 13 for(; isdigit(c); c = getchar()) ans = ans * 10 + c - '0'; 14 return ans * f; 15 } 16 struct Node{ 17 int l, r, s; 18 }t[maxn<<2]; 19 int n, l, u, s[maxn]; 20 void build(int u,int v,int w){ 21 t[w].l = u; t[w].r = v; 22 if (u == v){ 23 t[w].s = s[u]; return; 24 } 25 int mid = (u + v) >> 1; 26 build(u,mid,w<<1); build(mid+1,v,w<<1|1); 27 t[w].s = max(t[w<<1].s, t[w<<1|1].s); 28 } 29 int query(int u,int v,int w){ 30 if (t[w].l == u && t[w].r == v) return t[w].s; 31 int mid = (t[w].l + t[w].r) >> 1; 32 if (v <= mid) return query(u,v,w<<1); 33 else if (u > mid) return query(u,v,w<<1|1); 34 else return max(query(u,mid,w<<1), query(mid+1,v,w<<1|1)); 35 } 36 void work(){ 37 l = read(); u = read(); 38 s[0] = 0; rep(i,1,n) s[i] = s[i-1] + read(); 39 build(0,n,1); 40 int ans = 0x7fffffff; 41 rep(i,l,n) ans = min(ans, s[i] - query(max(0,i-u),i-l,1)); 42 printf("%d ",ans); 43 } 44 int main(){ 45 n = read(); 46 while (n){ 47 work(); n = read(); 48 } 49 return 0; 50 }