题目描述
现在请求你维护一个数列,要求提供以下两种操作:
1、 查询操作。
语法:Q L
功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。
限制:L不超过当前数列的长度。
2、 插入操作。
语法:A n
功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。
限制:n是整数(可能为负数)并且在长整范围内。
注意:初始时数列是空的,没有一个数。
输入输出格式
输入格式:
第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足(0<D<2,000,000,000)
接下来的M行,每行一个字符串,描述一个具体的操作。语法如上文所述。
输出格式:
对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。
输入输出样例
输入样例#1:
5 100 A 96 Q 1 A 97 Q 1 Q 2
输出样例#1:
96 93 96
说明
[JSOI2008]
题解:线段树端点维护区间最大值(3个点RE调不出来)
const
maxn=250000;
var
tree:array[1..maxn*4,1..3]of int64;
m,x,last,sum:int64;
i,n:longint;
ch:char;
procedure build(x:longint);
var
mid:longint;
begin
if tree[x,1]=tree[x,2] then exit;
mid:=(tree[x,1]+tree[x,2])shr 1;
tree[x,3]:=-maxlongint div 3;
tree[x+x,1]:=tree[x,1];tree[x+x,2]:=mid;
tree[x+x+1,1]:=mid+1;tree[x+x+1,2]:=tree[x,2];
build(x+x);
build(x+x+1);
end;
function max(a,b:int64):int64;
begin
if a>b then exit(a) else exit(b);
end;
procedure insert(p,x,y:int64);
var
mid:longint;
begin
if (tree[p,1]=x)and(tree[p,2]=x) then
begin
tree[p,3]:=y;
exit;
end;
mid:=(tree[p,1]+tree[p,2])shr 1;
if x<=mid then insert(p+p,x,y) else
if x>mid then insert(p+p+1,x,y);
tree[p,3]:=max(tree[p+p,3],tree[p+p+1,3]);
end;
function get(p,x,y:int64):int64;
var
mid:longint;
begin
if (tree[p,1]=x)and(tree[p,2]=y) then exit(tree[p,3]);
mid:=(tree[p,1]+tree[p,2])shr 1;
if y<=mid then get:=get(p+p,x,y) else
if x>mid then get:=get(p+p+1,x,y) else
get:=max(get(p+p,x,mid),get(p+p+1,mid+1,y));
end;
begin
readln(n,m);
tree[1,1]:=1;tree[1,2]:=n+100;
build(1);
for i:=1 to n do
begin
readln(ch,x);
if ch='A' then
begin
inc(sum);
insert(1,sum,(x+last)mod m);
end;
if ch='Q' then
begin
last:=get(1,sum-x+1,sum);
writeln(last);
end;
end;
end.