BZOJ 1012 [JSOI2008]最大数maxnumber 单调队列 线段树

Description

  现在请求你维护一个数列,要求提供以下两种操作:1、 查询操作。语法:Q L 功能:查询当前数列中末尾L
个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。2、 插入操作。语法:A n 功能:将n加
上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取
模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个
数。

Input

  第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足D在longint内。接下来
M行,查询操作或者插入操作。

Output

  对于每一个询问操作,输出一行。该行只有一个数,即序列中最后L个数的最大数。

Sample Input

5 100
A 96
Q 1
A 97
Q 1
Q 2

Sample Output

96
93
96

HINT

  数据如下http://pan.baidu.com/s/1i4JxCH3

题解:

一眼线段树,很水,但还有另一种很简单的做法,就是用单调队列

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int num[233333], tot = 0;
int maxx[233333];
int main()
{
	freopen("1012.in", "r", stdin);
	freopen("1012.out", "w", stdout);
	int m, d, t = 0;
	cin >> m >> d;
	for (int i = 1; i <= m; i++)
	{
		char a = getchar();
		while (a != 'A' && a != 'Q')
			a = getchar();
		int b;
		scanf("%d", &b);
		if (a == 'A')
		{
			num[++tot] = (b + t) % d;
			for (int j = tot; j; j--)
			{
				if (maxx[j] < num[tot])
					maxx[j] = num[tot];
				else
					break;
			}
		}
		else
			printf("%d\n", t = maxx[tot - b + 1]);
	}
	return 0;
}

当然线段树也可以

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int d, pos = 1, ls;
struct xds
{
	int l, r;
	ll maxx;
}tree[233333 * 4];
void build(int p, int l, int r)
{
	tree[p].l = l;
	tree[p].r = r;
	if (l == r)
		return ;
	int mid = (l + r) >> 1;
	build(p << 1, l, mid);
	build(p << 1 | 1, mid + 1, r);
}
void change(int p, int l, int r, ll x)
{
	if (l <= tree[p].l && tree[p].r <= r)
	{
		tree[p].maxx += (ll)x;
		return ;
	}
	int mid = (tree[p].l + tree[p].r) >> 1;
	if (l <= mid)	change(p << 1, l, r, x);
	if (r > mid)	change(p << 1 | 1, l, r, x);
	tree[p].maxx = max(tree[p << 1].maxx, tree[p << 1 | 1].maxx);
}
ll ask(int p, int l, int r)
{
	if (l <= tree[p].l && tree[p].r <= r)
	{
		return tree[p].maxx;
	}
	ll ans = 0;
	int mid = (tree[p].l + tree[p].r) >> 1;
	if (l <= mid)	ans = max(ans, ask(p << 1, l, r));
	if (r > mid)	ans = max(ans, ask(p << 1 | 1, l, r));
	return ans;
}
int main()
{
	freopen("1012.in", "r", stdin);
	freopen("1012.out", "w", stdout);
	int m, t = 0;
	cin >> m >> d;
	build (1, 1, 200000);
	for (int i = 1; i <= m; i++)
	{
		char a = getchar();
		while (a != 'A' && a != 'Q')
			a = getchar();
		int q;
		scanf("%d", &q);
		if (a == 'A')
		{
			change(1, pos, pos, (q+t)%d);
			pos++;
		}
		if (a == 'Q')
		{
			ls = pos - q;
			if (pos - q < 0)
				ls = 0;
			t = ask(1, ls, pos);
			printf("%d\n", t);
		}
	}
	return 0;
}

 

上一篇
下一篇