POJ-4040(单调队列)(Non-negative Partial Sums )

本文讨论了如何处理给定循环队列的问题,包括序列的形成与求和操作,利用单调队列和滚动子序列求和的方法来解决特定条件下的问题。详细解释了算法的实现步骤和背后的逻辑。
【转载自】http://blog.ac521.org/?p=123
【题目描述】
给定一个长n的循环队列(n<=1000000),可以循环形成序列(共n种),对于每种序列求前i项和sum(i),求形成的循环序列有多少种 满足任意的sum(i)>=0;
【解题思路】

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

#define N 1000002
int num[N * 2];
int q[N * 2], p[N * 2];
char s[N * 3];
int head, rear; 
int main() 
{
	int n, m, i, j;
	while (scanf("%d", &n) == 1 && n != 0) {
		int end = n * 2;
		getchar();
		gets(s);
		int index = 0, l = strlen(s);
		int number = 0;
		int tag = 0;
		for (i = 0; i < l; ++i) {
			if (s[i] == '-') {
				tag = 1;
				continue;
			}
			if (isdigit(s[i])) {
				number = number * 10 + s[i] - '0';
			} else {
				if (tag == 1) number *= -1;
				num[index++] = number;
				num[index + n - 1] = number;
				tag = 0;
				number = 0;
			}
		}
		if (index < n) {
			if (tag == 1) number *= -1;
			num[index++] = number;
			num[index + n - 1] = number;
		}
		for (i = 1; i < end; ++i)
			num[i] += num[i - 1];
		head = 0, rear = -1;
		m = 0;
		for (i = 0; i < end; ++i) {
			while (head <= rear && num[i] <= q[rear])
				rear--;
			q[++rear] = num[i];
			p[rear] = i;
			if (i >= n) {
				while (head <= rear && p[head] < i - n + 1)
					head++;
				int sum = num[i - n];
				if (q[head] - sum >= 0)
					++m; 
			}
		}
		printf("%d\n", m);

	}
	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值