P3203 [HNOI2010]弹飞绵羊
分块以后就很简单了,可以直接搞。
首先预处理,求出一个 \(get_i\) 和相对应的 \(pace_i\) 代表从 \(i\) 点一直弹到下一个块的地方和步数。那我们查询的时候每一次都是可以在 \(\sqrt{N}\) 的次数内弹到终点的。
关于修改,就是块里面可能会有一个点 \(j\) 会弹到 \(i\) 这里,借助 \(i\) 来弹到下一个块。这样子就保证了修改在整个块里面,操作同样是 \(\sqrt{N}\) 的。
然后注意弹出了以后要判一下边界,不然会溢出导致很多神奇的东西。
// luogu-judger-enable-o2
var
bounce,get,pace:array [-1..200007] of longint;
node_num,block_num,mode,ans,l,k,i,j,n,m:longint;
function Locate(node:longint):longint;begin exit((node-1) div node_num+1); end;
procedure Ready;
begin
read(n); node_num:=trunc(sqrt(n)); block_num:=Locate(n);
for i := 1 to n do read(bounce[i]); read(m);
for i:=n downto 1 do
begin
l:=Locate(i)*node_num;
if (i+bounce[i]>n) then begin get[i]:=0; pace[i]:=1; continue; end;
if (i+bounce[i]>l) then begin get[i]:=i+bounce[i]; pace[i]:=1; end else
begin get[i]:=get[i+bounce[i]]; pace[i]:=pace[i+bounce[i]]+1; end;
end;
end;
begin
Ready;
for i:=1 to m do
begin
read(mode);
if mode=1 then
begin
ans:=0; read(l); inc(l); j:=l;
while j>0 do begin inc(ans,pace[j]); j:=get[j]; end;
writeln(ans);
end else
begin
read(l,k); inc(l); bounce[l] := k;
for j:=l downto(Locate(l)-1)*node_num+1 do
begin
if (j+bounce[j]>n) then begin get[j]:=0; pace[j]:=1; continue; end;
if (j+bounce[j]>Locate(l)*node_num) then begin get[j]:=j+bounce[j]; pace[j]:=1; end else
begin get[j]:=get[j+bounce[j]]; pace[j]:=pace[j+bounce[j]]+1; end;
end;
end;
end;
end.
完结撒花!✿✿ヽ(゚▽゚)ノ✿