[JSOI2008]最大数maxnumber
Time Limit: 3 Sec Memory Limit: 162 MB
Description
现在请求你维护一个数列,要求提供以下两种操作: 1、 查询操作。语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。 2、 插入操作。语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个数。
Input
第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足(0
Output
对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。
Sample Input
5 100
A 96
Q 1
A 97
Q 1
Q 2
Sample Output
96
93
96
题解
树状数组(终于不水题了)(其实还是水~黑)
首先是添加进数组
- 添加进树状数组y[tail],然后需要比较的是y[tail- 20 ],y[tail- 21 ],y[tail- 22 ]……y[tail-lowbit(tail)+1]
然后是区间查询
- 我们认为区间左端点为l右端点为r,右端点的范围为[r-lowbit(r)+1,r],如果r-lowbit(r)+1在左端点l内或l上,则比较y[r],然后r变为r-lowbit,否则r变为r-1
var
x,y:array[0..200000]of longint;
i,j,k:longint;
m,d,a,t,l,r:longint;
v:char;
function max(a,b:longint):longint;
begin
if a>b
then exit(a)
else exit(b);
end;
function lowbit(a:longint):longint;
begin
exit(a and(-a));
end;
begin
readln(m,d); t:=0; x[0]:=0;
for i:=1 to m do
begin
readln(v,a);
if v='A'
then
begin
inc(x[0]);
x[x[0]]:=(a+t) mod d;
y[x[0]]:=x[x[0]];
j:=1;
while j<lowbit(x[0]) do
begin
y[x[0]]:=max(y[x[0]],y[x[0]-j]);
j:=j*2;
end;
end
else
begin
l:=x[0]-a+1; r:=x[0]; t:=0;
while l<=r do
if r-lowbit(r)+1>=l
then begin t:=max(t,y[r]); dec(r,lowbit(r)); end
else begin t:=max(t,x[r]); dec(r); end;
writeln(t);
end;
end;
end.