1. 程式人生 > >Sicily 1800. Sequence

Sicily 1800. Sequence

ems define 範圍 integer def soft none algo tdi

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\n",ans);
43 }
44 int main(){
45     n = read();
46     while (n){
47         work(); n = read();
48     } 
49     return 0;
50 }
View Code

Sicily 1800. Sequence