您的位置:首页 > 其它

hdu 4193 Non-negative Partial Sums 单调队列

2012-07-10 13:12 507 查看
hdu 4193 Non-negative Partial Sums

//hdu 4193 Non-negative Partial Sums
//单调队列

//看了这个解题报告才有所理解的http://blog.ac521.org/?p=123
//题意:给定一个长n的循环队列(n<=1000000),可以循环形成序列(共n种),
//对于每种序列求前i项和sum(i),求形成的循环序列有多少种 满足
//任意的sum(i)>=0;(0<i<=N)。

//思路: 首先用循环序列的一般处理方法,两个接在一起,
//然后处理出来sum,使用单调队列,滚动求长n的子序列的最小值。
//如果最小值减去前面的sum仍然是非负的,则计数。

#include <stdio.h>
#include <string.h>

const int N = 1000005 * 2;

int num
, que
;

int main()
{
int n;
while(scanf("%d", &n), n)
{
for(int i = 0; i < n; ++i)
{
scanf("%d", &num[i]);
num[n+i] = num[i];
}
int N = n;
n *= 2;
for(int i = 1; i < n; ++i)
num[i] += num[i-1];
int head = 0, tail = 0, ans = 0;

for(int i = 0; i < n; ++i)
{
while(head < tail && num[i] <= num[ que[tail-1] ])
tail--;
que[tail++] = i;
//以下N=n/2
//从i 到 i-N 之间有N个数,que[head]即为这个跨度间的最小值
//而i到这个跨度之间的任一个数的距离都不会超过N
//则若 i-N 到que[head]之间的所有数的和肯定最小
//因为我们其实是确定i-N后求出i-N所能到达的N个数之间求出最小区间和
//减去i的区间和肯定最小
//我所没理解过来的是i-n到i之间有N+1个数,若num[N+1]-num
>= 0则答案会多出1来
//也不知道会不会出现这种可能

//记得这里是 i>= N 因为我下标是从0开始的,这个让我调试了好久才找到···
if(i >= N && num[ que[head] ] - num[i-N] >= 0)
ans++;
while(head < tail && i - N + 1 >= que[head])
head++;
}
printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: