【题意】:给定一个长度为n的环序列,可以形成n种链序列,问有多少种链序列满足所有前i项和都大于等于0(1<=i<=n)。
【题解】:首先把环序列切断,变成两倍长度。预处理所有前 i 项和。
枚举起点j,使用单调队列求区间最小值,如果最小值大于sum[j]则答案加一。
【代码】:
1 #include "iostream"
2 #include "cstdio"
3 #include "cstring"
4 #include "algorithm"
5 #include "vector"
6 #include "queue"
7 #include "cmath"
8 #include "string"
9 #include "cctype"
10 #include "map"
11 #include "iomanip"
12 using namespace std;
13 #define pb push_back
14 #define mp make_pair
15 #define fi first
16 #define se second
17 #define lc(x) (x << 1)
18 #define rc(x) (x << 1 | 1)
19 #define lowbit(x) (x & (-x))
20 #define ll long long
21 #define maxn 1000050
22 int n;
23 int val[maxn];
24 int sum[maxn<<1];
25 int que[maxn<<1], head, tail;
26
27 int main() {
28 while(~scanf("%d", &n)) {
29 if(!n) break;
30 sum[0] = 0;
31 for(int i = 1; i <= n; i++) {
32 scanf("%d", &val[i]);
33 sum[i] = sum[i-1] + val[i];
34 }
35 for(int i = n + 1; i <= 2 * n; i++) {
36 sum[i] = sum[i-1] + val[i-n];
37 }
38 int ans = 0;
39 head = tail = 0;
40 que[tail++] = 0;
41 for(int i = 1; i <= 2 * n; i++) {
42 if(i > n) {
43 while(head < tail && que[head] < i - n - 1) head++;
44 if(sum[que[head]] >= sum[i-n-1]) ans++;
45 }
46 while(head < tail && sum[que[tail-1]] > sum[i]) tail--;
47 que[tail++] = i;
48 }
49 cout << ans << endl;
50 }
51
52 return 0;
53 }
54