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 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;
}
时间: 2024-10-11 05:46:22

hdu4193---Non-negative Partial Sums(单调队列 or 单调栈)的相关文章

浅谈单调队列、单调栈

       初谈这个话题,相信许多人会有一种似有所悟,但又不敢确定的感觉.没错,这正是因为其中"单调"一词的存在,所谓单调是什么,学过函数的people都知道单调函数或者函数的单调性,直白一点说单调就是一直增或一直减.例如:1,3,5,9就是一个单调增数列,数列中不存在后一个数比前一个数小的现象.那么同样,在这里谈到的话题也有类似特点.        先说一下单调队列吧!      单调队列,就是一个符合单调性质的队列,它同时具有单调的性质以及队列的性质.他在编程中使用频率不高,但却

单调队列,单调栈相关

说起这个话题,应该很多人会有一种似有所悟,但又不敢确定的感觉. (我差不多就是那样) 没错,这正是因为其中“单调”一词的存在. 那么单调是什么? 学过函数的人都知道单调函数或者函数的单调性吧 其实直白一点说单调,就是一直增或一直减. eg:1,3,5,9就是一个单调增数列,数列中不存在后一个数比前一个数小的现象. 那么同样,在这里谈到的话题也有类似特点. (一)单调队列 其实就是一个符合单调性质的队列,但它同时具有单调的性质以及队列的性质. 使用频率不算高,但却占有至关重要的地位.它的作用很简单

单调队列、单调栈、优先队列模板

目录 单调栈.单调队列及优先队列 1.单调队列 2.单调栈 3.优先队列 单调栈.单调队列及优先队列 1.单调队列 单调队列的描述:指队列中元素之间关系具有单调性,而且队首和队尾都可以出队,但是只有队尾可以进行入队操作.其重要作用是找到前n个后者后n个数的最值. 其具体操作是:假设单调队列是单调递减队列,假设在插入元素v时,将队列尾部的元素同v比较,如果队列尾部的元素不大于元素v,我们直接删除队尾元素,再将队尾元素与v比较,直至队尾元素比v大,这个时候我们将v插入队尾.其实现代码如下: int

单调队列与单调栈用法详解

1.单调栈 单调栈是指一个栈内部的元素具有严格单调性的一种数据结构,分为单调递增栈和单调递减栈. 其具有以下两个性质: 1,满足栈底到栈顶的元素具有严格单调性. 2,满足栈的先进后出特性,越靠近栈顶的元素越后出栈. 单调队列同理,其严格单调性与单调栈相同. 但该队列中的元素满足先进先出特性,越靠近队列头的元素越先出队. 原文地址:https://www.cnblogs.com/xiefengze1/p/8495272.html

单调队列以及单调队列优化DP

单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2.优化DP 例题引入: https://www.luogu.org/problemnew/show/P1440 一个含有n项的数列(n<=2000000),求出每一项前的m个数到它这个区间内的最小值.若前面的数不足m项则从第1个数开始,若前面没有数则输出0. 例题解答: 首先看到题目可以很快想到O(

单调队列

先放上luogu的题目链接--滑稽窗口 然后我们再来讲单调队列 单调队列是指这样一种队列:在队列中的元素为单调递增状态或单调递减状态. 例如1 2 3 4 5和9 2 1都是单调队列,但1 2 2 3 4和4 3 4 5就不是单调队列. 但普通队列明显是维持不了单调队列的性质的. 为了维持单调队列的单调性质,我们只好想一些方法.方法就是修改队列的性质.单调队列不仅队头可以出队,队尾也可以出队. 比如说有一个单调队列是 1 3 7 8 现在突然要从队尾进来一个6如果单纯的把6插进队尾的话,那这个队

POJ2823 Sliding Window (单调队列)

POJ2823 Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 38342   Accepted: 11359 Case Time Limit: 5000MS Description An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the ve

小结:单调栈 &amp; 单调队列

概要: 对于维护信息具有单调性的性质或者问题可以转化为具有单调性质的模型的题,我们可以考虑用单调栈或单调队列. 技巧及注意: 技巧很多,只要能将问题转化为单调性问题,就好解决了. 当维护固定长度的单调区间,我们考虑用单调队列,如[BZOJ]3314: [Usaco2013 Nov]Crowded Cows(单调队列) 单调栈维护长度时要进行及时更新,例如:[BZOJ]3039: 玉蟾宫(DP/单调栈) 假设完美状态后再进行减法原理,例如:[BZOJ]1628 && 1683: [Usaco

POJ 2823 Sliding Window 【单调队列】

题目链接:http://poj.org/problem?id=2823 题目大意:给出一组数,一个固定大小的窗口在这个数组上滑动,要求出每次滑动该窗口内的最大值和最小值. 这就是典型的单调队列,单调队列的作用就在此.单调队列的队首为区间内的最值,但是整个队列不用保持单调. 用两个队列分别处理最大值和最小值,在此说明一下最大值: 往队列中添加值num时,从队尾开始扫,直到遇到一个小于num的d值,将num插入d的后一位.之后的元素全部无效化(不管后面的元素就行).查找最大值的时候,从队首开始找,如