这道题听说要用splya做,但是我还不会写,所以我找了找题解,最后找到用分块原理做的。
代码很简洁,也很清楚。
(参考资料:http://blog.csdn.net/jasonzhu8/article/details/5738434)
var
o,t,w,s:array[0..200000] of longint;
n,task,i,j,k,l:longint;
procedure new;
begin
j:=i+t[i];
if o[i]=o[j] then begin
w[i]:=w[j]; s[i]:=s[j]+1;
end else begin
w[i]:=j; s[i]:=1;
end;
end;
begin
readln(n);
for i:=1 to n do read(t[i]);
k:=round(sqrt(n));
l:=1; j:=0;
for i:=1 to n do o[i]:=((i-1) div k)+1;
for i:=n downto 1 do new;
readln(task);
for task:=1 to task do begin
read(l);
if l=1 then begin
readln(l);inc(l);
k:=0;
while l<=n do begin
inc(k,s[l]);
l:=w[l];
end;
writeln(k);
end else begin
readln(i,j);inc(i);
t[i]:=j;k:=o[i];
for i:=i downto 1 do if o[i]=k then new else break;
end;
end;
end.
o[i]:i属于第o[i]块
t[i]:i的弹性系数
w[i]: i的块外下一个是w[i]
s[i]:i在块内需要几步走出
改变k就在块内改变,询问就在块外循环,均摊复杂度O(N*LOG(N))