HDU2430 beans



链接:http://acm.hdu.edu.cn/showproblem.php?pid=2430

题目大概讲述:给你n堆豆子,按序号排列,现让你任取连续堆豆子,将其装在许多大小为p的袋子里,剩余的豆子不能超过k,问最多能装多少袋?

这道题若是用单调队列做:

你应当找出每个位置,和在其前面的与其坐标差距最大的位置,并且两位置之间的豆子总数%p<=k。

用单调递增队列来做,余数大的堆被排在后面,余数小的堆被排在前面,然后创立一个大小为n的数组。遍历一遍,找到每个位置对应的位置,再用数组保存起来,遍历一遍,求出最大值。



#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

typedef struct Node
{
	int mod;
	int pos;
}node;
node res[1000010];
__int64 all[1000010];
int mmin[1000010];
node que[1000010];

bool com(node a, node b)
{
	if (a.mod != b.mod)
		return a.mod < b.mod;
	return a.pos < b.pos;
}

int main()
{
	int times;
	int cl = 0;
	scanf("%d", ×);
	while (times--)
	{
		memset(que, 0, sizeof(que));
		memset(res, 0, sizeof(res));
		memset(all, 0, sizeof(all));
		memset(mmin, 0, sizeof(mmin));
		int n, p, k;
		scanf("%d%d%d", &n, &p, &k);
		for (int i = 1; i <= n; i++)
		{
			scanf("%d", &all[i]);
			all[i] += all[i - 1];
			res[i].pos = i;			
			res[i].mod = all[i] % p;
		}
		sort(res+1, res + n + 1, com);
		int tail = 1, head = 0;
		__int64 ans = -1;
		for (int i = 1; i <= n; i++)
		{
			if (tail <= head )
				mmin[res[i].pos] = que[tail].pos;
			else
				mmin[res[i].pos] = -1;
			while (tail <= head&&res[i].pos<que[head].pos)
				head--;
			que[++head] = res[i];
			while (tail <= head&&(res[i+1].mod - que[tail].mod) > k)
				tail++;	
		}
		for (int i = 1; i <= n; i++)
		{
			if (all[i] % p <= k)
			{
				if (ans < all[i] / p)
				{
					ans = all[i] / p;
				}
			}
			else
				if (mmin[i] != -1&&mmin[i]<i )
				{
						if (ans < (all[i] - all[mmin[i]])/p)
							ans = (all[i] - all[mmin[i]]) / p;
				}
		}
		printf("Case %d: %I64d\n", ++cl, ans);

	}
	return 0;
}



你可能感兴趣的:(HDU2430 beans)