题意:
给定一个序列,支持以下操作:
- 对一段下标是等差数列的子序列进行求最大值操作(参见输入格式);
- 单点修改。
不知怎么回事,29号下午许多神犇好像在组队做这题。。于是ZMOIYNLP、Angelic47神犇邀请我这个蒟蒻一起做。。。。。
其实想法很简单,建许多线段树,不在线段树的情况暴力。线段树太多会MLE,太少时间效率我们认为不高(事实证明这是不准确的)。。。
于是我就把步长为100以下所有都建了线段树。。。。。发现T了。。。
然后我就乱搞,试图减小常数。。。但见效甚微
我们偶然的只把步长为4以下所有建了线段树。。。就飞快了。。。BZOJ上当前排第三。。
ZMOIYNLP的分块马上就要超过我啦!!!Angelic47的神奇算法也即将一飞冲天!!!
var
a:array[0..70001]of longint;
lch,rch,maxx:array[0..10000000]of longint;//事实上还是开大了
ed,root:array[0..200,0..200]of longint;//ed[i,j]表示步长为i,从原序列中第j个开始的等差子序列的长度。root[i,j]表示步长为i,从原序列中第j个开始的等差子序列在线段树中的根
n,m,i,x,y,tot,step,st,bound,rt,ans,op,up:longint;
function max(a,b:longint):longint;inline;
begin
if a>b then exit(a);exit(b);
end;
procedure build(l,r,i:longint);
var mid:longint;
begin
if l=r then begin maxx[i]:=a[st+(l-1)*step];exit;end;
mid:=(l+r)>>1;
inc(tot);
lch[i]:=tot;
build(l,mid,lch[i]);
inc(tot);
rch[i]:=tot;
build(mid+1,r,rch[i]);
//maxx[i]:=max(maxx[lch[i]],maxx[rch[i]]);
if maxx[lch[i]]>maxx[rch[i]] then maxx[i]:=maxx[lch[i]] else maxx[i]:=maxx[rch[i]];
end;
function get(s,t,l,r,i:longint):longint;
var mid,a,b:longint;
begin
if (s<=l)and(t>=r) then exit(maxx[i]);
mid:=(l+r)>>1;
if s>mid then exit(get(s,t,mid+1,r,rch[i]));
if t<=mid then exit(get(s,t,l,mid,lch[i]));
//exit(max(get(s,t,l,mid,lch[i]),get(s,t,mid+1,r,rch[i])));
a:=get(s,t,l,mid,lch[i]);
b:=get(s,t,mid+1,r,rch[i]);
if a>b then exit(a) else exit(b);
end;
procedure update(p,l,r,i:longint);
var mid:longint;
begin
if l=r then begin maxx[i]:=a[st+(p-1)*step];exit;end;
mid:=(l+r)>>1;
if p<=mid then update(p,l,mid,lch[i]) else update(p,mid+1,r,rch[i]);
//maxx[i]:=max(maxx[lch[i]],maxx[rch[i]]);
//我原来脑残的打了maxx[i]:=max(lch[i],rch[i]);结果蹦出来许多很大的数
if maxx[lch[i]]>maxx[rch[i]] then maxx[i]:=maxx[lch[i]] else maxx[i]:=maxx[rch[i]];
end;
begin
up:=4;
//assign(input,'in');reset(input);
readln(n);
if n<up then bound:=n else bound:=up;
for i:=1 to n do read(a[i]);
for step:=1 to bound do
for st:=1 to step do
begin
inc(tot);
root[step,st]:=tot;
ed[step,st]:=(n-st)div step+1;
build(1,ed[step,st],tot);
end;
//writeln(tot);
readln(m);
for m:=1 to m do
begin
readln(op,x,y);
case op of
1:
begin
if y>bound then//暴力
begin
//pos:=x;
ans:=-maxlongint;
while x<=n do
begin
if a[x]>ans then ans:=a[x];
x:=x+y;
end;
writeln(ans);
continue;
end;
st:=(x-1)mod y+1;
rt:=root[y,st];
ans:=get((x-st)div y+1,ed[y,st],1,ed[y,st],rt);
writeln(ans);
end;
0:
begin
inc(a[x],y);
for step:=1 to bound do
begin
st:=(x-1)mod step+1;
rt:=root[step,st];
update((x-st)div step+1,1,ed[step,st],rt);
end;
end;
end;
end;
close(input);close(output);
end.
【后记】好了,ZMOIYNLP已经第一啦!!!