【题意】:给定一个长度为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