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.

 

posted on 2014-01-07 10:43  BLADEVIL  阅读(261)  评论(0编辑  收藏