hdu4193---Non-negative Partial Sums(单调队列 or 单调栈)

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 fi rst 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 fi rst 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;
}

你可能感兴趣的:(单调栈)