HDU 4193 Non-negative Partial Sums【单调队列】

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4193

题意:

给定序列,可以把后面的连续的部分移到最前面来,问多少种移法使得最终得到的序列的前 i 项和均大于等于0( 1in )?

分析:

先将数组前后拼接起来,记录每个位置的前缀和。然后去找长度为n的滑动窗口,在这个窗口内,要保证前 i 项和大于等于0,也即区间 [i,n+i] 之间的找到的最小的前缀和要比 a[i1] 大。而不涉及修改,这个最小前缀和的获取和维护就利用单调队列即可~

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn = 2e6 + 5;
int q[maxn], a[maxn];
int head, rear;
int n, cnt;
void inque(int i)
{
    while(rear >= head && a[q[rear]] >= a[i]) rear--;
    q[++rear] = i;
}
void outque(int i)
{
    if(q[head] < i - n + 1){
        head++;
    }
}
int main (void)
{
    while(scanf("%d", &n) && n){
        head = 0, rear = 0;
        memset(a, 0, sizeof(a));
        memset(q, 0, sizeof(q));
        for(int i = 0; i < n; i++){
            scanf("%d", &a[i]);
            a[n + i] = a[i];
        }
        for(int i = 1; i < 2 * n; i++)
             a[i] += a[i - 1];
       for(int i = 0; i < n; i++)
            inque(i);
       int cnt = 0;
       for(int i = n; i < 2 * n; i++){
            outque(i);
            inque(i);
            if(a[q[head]] - a[i- n] >= 0)  cnt++;
        }
        printf("%d\n", cnt);
    }
    return 0;
}
/*
5
-1 -2 -3 -4 -5
*/

你可能感兴趣的:(HDU 4193 Non-negative Partial Sums【单调队列】)