bzoj 2002 LCT

LCT最基础的题,就用到了一个ACCESS操作

首先我们将这个绵羊弹飞的情况看成一颗树,那么假设X点被弹飞到

Y点,那么Y为X的父亲节点,弹飞的话父亲节点为n+1(虚设)

那么每个询问就是询问X点到根节点n+1的路径长度(节点数)

每个修改操作就是将以X为根节点的子树和X的父亲断开,连接到Y上

这样简单的维护森林连通性的问题,动态树中的LCT解决就行了

/**************************************************************

    Problem: 2002

    User: BLADEVIL

    Language: Pascal

    Result: Accepted

    Time:2372 ms

    Memory:4328 kb

****************************************************************/

 

//By BLADEVIL

var

    n, m                :longint;

    father, size        :array[-1..200010] of longint;

    son                 :array[-1..200010,0..2] of longint;

    root                :array[-1..200010] of boolean;

 

procedure update(x:longint);

begin

    size[x]:=size[son[x,0]]+size[son[x,1]]+1;

end;

     

procedure left_rotate(x:longint);

var

    y                   :longint;

begin

    y:=son[x,1];

    son[x,1]:=son[y,0];

    father[son[x,1]]:=x;

    son[y,0]:=x;

    if x=son[father[x],0] then

        son[father[x],0]:=y else

    if x=son[father[x],1] then

        son[father[x],1]:=y;

    father[y]:=father[x];

    father[x]:=y;

    root[y]:=root[x] xor root[y];

    root[x]:=root[x] xor root[y];

    update(x); update(y);

end;

 

procedure right_rotate(x:longint);

var

    y                   :longint;

begin

    y:=son[x,0];

    son[x,0]:=son[y,1];

    father[son[x,0]]:=x;

    son[y,1]:=x;

    if x=son[father[x],0] then

        son[father[x],0]:=y else

    if x=son[father[x],1] then

        son[father[x],1]:=y;

    father[y]:=father[x];

    father[x]:=y;

    root[y]:=root[y] xor root[x];

    root[x]:=root[y] xor root[x];

    update(x); update(y);

end;

     

procedure splay(x:longint);

begin

    while not root[x] do

        if x=son[father[x],1] then

            left_rotate(father[x]) else

            right_rotate(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;

     

procedure init;

var

    i                   :longint;

begin

    read(n);

    for i:=1 to n do

    begin

        read(father[i]);

        father[i]:=father[i]+i;

        if father[i]>n then father[i]:=n+1;

    end;

    read(m);

end;

 

procedure main;

var

    i                   :longint;

    x, y, z             :longint;

begin

    for i:=1 to n+1 do size[i]:=1;

    fillchar(root,sizeof(root),true);

    for i:=1 to m do

    begin

        read(x);

        if x=1 then

        begin

            read(y); inc(y);

            access(y);

            writeln(size[son[y,0]]);

        end else

        begin

            read(y,z); inc(y);

            splay(y);

            father[son[y,0]]:=father[y];

            root[son[y,0]]:=true;

            son[y,0]:=0; 

            size[y]:=size[son[y,1]]+1;

            father[y]:=y+z;

            if father[y]>n then father[y]:=n+1;

        end;

    end;

end;

     

begin

    init;

    main;

end.

 

你可能感兴趣的:(ZOJ)