Problem Description
You are given a sequence of n numbers a0,…, an-1. A cyclic shift by k positions (0<=k<=n-1) results in the following sequence: ak ak+1,…, an-1, a0, a1,…, ak-1. How many of the n cyclic shifts satisfy the condition that the sum of the first i numbers is greater than or equal to zero for all i with 1<=i<=n?
Input
Each test case consists of two lines. The first contains the number n (1<=n<=106), the number of integers in the sequence. The second contains n integers a0,…, an-1 (-1000<=ai<=1000) representing the sequence of numbers. The input will finish with a line containing 0.
Output
For each test case, print one line with the number of cyclic shifts of the given sequence which satisfy the condition stated above.
Sample Input
3
2 2 1
3
-1 1 1
1
-1
0
Sample Output
3
2
0
Source
SWERC 2011
Recommend
lcy | We have carefully selected several similar problems for you: 4190 4192 4187 4188 4189
我对这题的第一反应就是可以转换为滑窗问题,然后单调队列解决
这里我用的是单调栈的做法,先把序列扩展一倍,然后从右往左记录后缀和,然后开始维护一个递增的单调栈,如果栈顶小于当前要入栈的sum值,就去掉,假设栈顶位置是i,现在要入栈的位置是j,那么说明区间[i, j - 1]的值是负的,所以以第i个元素开始的序列是不合法的
最后统计合法的即可
复杂度O(n)
/*************************************************************************
> File Name: hdu4193.cpp
> Author: ALex
> Mail: [email protected]
> Created Time: 2015年05月11日 星期一 14时13分22秒
************************************************************************/
#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <map>
#include <list>
#include <bitset>
#include <set>
#include <vector>
using namespace std;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double eps = 1e-15;
typedef long long LL;
typedef pair <int, int> PLL;
static const int N = 1100100;
int arr[N << 1];
int sum[N << 1];
stack <PLL> Stack;
bool flag[N << 1];
int main() {
int n;
while (~scanf("%d", &n), n) {
sum[2 * n] = 0;
for (int i = 1; i <= n; ++i) {
scanf("%d", &arr[i]);
flag[i] = 1;
}
for (int i = n + 1; i <= 2 * n - 1; ++i) {
arr[i] = arr[i - n];
}
for (int i = 2 * n - 1; i >= 1; --i) {
sum[i] = sum[i + 1] + arr[i];
}
// Top = 0;
while (!Stack.empty()) {
Stack.pop();
}
for (int i = 1; i <= 2 * n - 1; ++i) {
if (Stack.empty()) {
Stack.push(make_pair(sum[i], i));
}
else {
while (!Stack.empty()) {
PLL u = Stack.top();
if (u.first >= sum[i]) {
break;
}
Stack.pop();
int len = i - u.second;
if (len <= n) {
flag[u.second] = 0;
}
}
Stack.push(make_pair(sum[i], i));
}
}
while (!Stack.empty()) {
PLL u = Stack.top();
Stack.pop();
if (u.first < 0 && u.second <= n) {
flag[u.second] = 0;
}
}
int ans = 0;
for (int i = 1; i <= n; ++i) {
ans += flag[i];
}
printf("%d\n", ans);
}
return 0;
}