Description
现在请求你维护一个数列,要求提供以下两种操作:1、 查询操作。语法:Q L 功能:查询当前数列中末尾L
个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。2、 插入操作。语法:A n 功能:将n加
上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取
模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个
数。
个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。2、 插入操作。语法:A n 功能:将n加
上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取
模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个
数。
Input
第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足D在longint内。接下来
M行,查询操作或者插入操作。
M行,查询操作或者插入操作。
Output
对于每一个询问操作,输出一行。该行只有一个数,即序列中最后L个数的最大数。
Sample Input
5 100
A 96
Q 1
A 97
Q 1
Q 2
A 96
Q 1
A 97
Q 1
Q 2
Sample Output
96
93
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;
}