bzoj 2002 link cut tree(LCT)

来源:互联网 发布:mac腾讯视频 编辑:程序博客网 时间:2024/05/20 19:29

题意:n个位置,第i个位置有一个弹力系数为ki的装置,编号从0~n-1,会被弹到i+ki的位置。如果i+ki处无装置,则弹飞否则继续。

两个操作:

1、1 x 输出从第x处开始弹几次被弹飞

2、2 x y x处装置的弹力系数改为y

LCT基础题

注意编号是0~n-1,这里我们都加1处理,使得范围为1~n

我们很容易发现一个性质:有无数个点可以到达同一个点,但一个点只能到达一个固定的点

所以令father[i]=i+ki

对于i>n所有已经弹飞的点,father[i]=0;

对于i+ki>n的点,干脆直接让father[i]=n+1

那么我们对于操作1,就是输出在x所对应的Auxiliary tree中,x到根节点的节点数

对于操作2,就是更改一下father[x]

因为我们连的是有向边,所以不需要翻转

所以,先access(x),再splay(x),把son[x,0]断掉独立出去,再更新father[x],更新方法见上

var        n,m,p,x,y        :longint;        father,size      :array[-1..200010] of longint;        son              :array[-1..200010,0..1] of longint;        root             :array[-1..200010] of boolean;        i                :longint;procedure update(x:longint);begin   size[x]:=size[son[x,0]]+size[son[x,1]]+1;end;procedure r_ro(f:longint);var        x:longint;begin   x:=son[f,0];   son[f,0]:=son[x,1];   father[son[x,1]]:=f;   if f=son[father[f],0] then son[father[f],0]:=x     else if f=son[father[f],1] then son[father[f],1]:=x;   father[x]:=father[f];   father[f]:=x;   son[x,1]:=f;   root[x]:=root[x] xor root[f];   root[f]:=root[x] xor root[f];   update(f); update(x);end;procedure l_ro(f:longint);var        x:longint;begin   x:=son[f,1];   son[f,1]:=son[x,0];   father[son[x,0]]:=f;   if f=son[father[f],0] then son[father[f],0]:=x     else if f=son[father[f],1] then son[father[f],1]:=x;   father[x]:=father[f];   father[f]:=x;   son[x,0]:=f;   root[x]:=root[f] xor root[x];   root[f]:=root[f] xor root[x];   update(f); update(x);end;procedure splay(x:longint);begin   while not root[x] do     if x=son[father[x],0] then r_ro(father[x]) else l_ro(father[x]);end;procedure access(x:longint);var        y:longint;begin   splay(x);   while father[x]<>0 do   begin      y:=father[x];      splay(y);      root[son[y,1]]:=true;      root[x]:=false;      son[y,1]:=x;      update(y);      splay(x);   end;end;begin   read(n);   for i:=1 to n do   begin      read(x);      if i+x>n then father[i]:=n+1 else father[i]:=i+x;   end;   fillchar(son,sizeof(son),255);   fillchar(root,sizeof(root),true);   for i:=1 to n+1 do size[i]:=1;   read(m);   for i:=1 to m do   begin      read(p,x);      inc(x);      if p=1 then      begin         access(x);         splay(x);         writeln(size[son[x,0]]);      end else      begin         read(y);         if x+y>n then y:=n+1 else y:=x+y;         access(x);         splay(x);         father[son[x,0]]:=0;         root[son[x,0]]:=true;         son[x,0]:=-1;         update(x);         father[x]:=y;      end;   end;end.
—— by Eirlys








0 0
原创粉丝点击