您的位置:首页 > 其它

Hdu4193 Non-negative Partial Sums (单调队列)

2013-11-11 22:50 260 查看
题意:

给你一个n项的序列,每次可以把序列的首项移动到末尾,一共可以构成n种序列,问一共有多少种序列满足条件:序列的前i项和都大于等于0(i:1~n)。

思路:

遇到循环队列,很普遍的想法:用2倍的数组把数据再存一遍。

用sum数组预处理出前缀和,数据范围不会超int,这样sum中任意两项之差即为这一段的数字之和。

对于区间i-n+1 ~ i,(i>=n)如果该区间内最小的sum[k],(i-n+1<=k<=i)满足sum[k]-sum[i-n]>=0,那么该区间满足题意

问题转化为求滚动区间中的最小值,可用单调队列处理

换了一种单调队列的写法,可能这种更清晰

#include <cstdio>
#include <cstring>

const int N=2000005;

int data
,q
,sum
;
int front,rear,ans,n;

void In (int i)
{//单调递增队列,保证队首最小
	while (front<=rear && sum[q[rear]]>=sum[i])
		rear--;
	q[++rear]=i;
}

void Out (int i)
{
	if (q[front]<=i-n)//保证队列长度不超过n
		front++;
	if (sum[q[front]]-sum[i-n] >=0)
		ans++;
}

int main ()
{
	while (scanf("%d",&n),n)
	{
		front=0;
		rear=-1;
		ans=0;
		memset(sum,0,sizeof(sum));
		int i;
		for (i=1;i<=n;i++)
		{
			scanf("%d",&data[i]);
			data[i+n]=data[i];
		}
		for (i=1;i<2*n;i++)
			sum[i]+=sum[i-1]+data[i];
		for (i=1;i<n;i++)
			In (i);
		for (i=n;i<2*n;i++)
		{
			In(i);
			Out(i);
		}
		printf("%d\n",ans);
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: