[BZOJ2049] [Sdoi2008]Cave 洞穴勘测

传送门

http://www.lydsy.com/JudgeOnline/problem.php?id=2049

题目大意

支持删边+连边+查询是否连通

题解

LCT~

const
    maxn=10050;
var 
    son:array[0..maxn,1..2]of longint;
    fa,rev:array[0..maxn]of longint;
    i,j,k:longint;
    n,m,a,b:longint;
    cha,ch:char;
function isroot(a:longint):longint;
begin if (son[fa[a],1]<>a)and(son[fa[a],2]<>a) then exit(1) else exit(0); end;

procedure swap(var a,b:longint);
var c:longint;
begin c:=a; a:=b; b:=c; end;

procedure pushdown(a:longint);
begin
    if rev[a]=0 then exit;
    swap(son[a,1],son[a,2]);
    rev[son[a,1]]:=rev[son[a,1]] xor 1;
    rev[son[a,2]]:=rev[son[a,2]] xor 1;
    rev[a]:=0;
end;

procedure rotate(a,kind:longint);
var b,unkind:longint;
begin
    b:=fa[a]; unkind:=kind xor 3;   
    if son[fa[b],1]=b then son[fa[b],1]:=a else
    if son[fa[b],2]=b then son[fa[b],2]:=a;
    fa[a]:=fa[b]; 
    son[b,kind]:=son[a,unkind]; fa[son[a,unkind]]:=b; 
    son[a,unkind]:=b; fa[b]:=a; 
end;

procedure splay(a:longint);
var b,kind,unkind:longint;
begin
    pushdown(a);
    while isroot(a)=0 do
        begin
            b:=fa[a]; pushdown(fa[b]); pushdown(b); pushdown(a);
            if son[b,1]=a then kind:=1 else kind:=2; unkind:=kind xor 3;
            if isroot(b)=1 then rotate(a,kind)
            else
                if son[fa[b],kind]=b
                then begin rotate(b,kind); rotate(a,kind); end
                else begin rotate(a,kind); rotate(a,unkind); end;
        end;
end;

procedure access(a:longint);
var b:longint;
begin
    splay(a); son[a,2]:=0;
    while fa[a]<>0 do
        begin
            b:=fa[a];
            splay(b);
            son[b,2]:=a;
            splay(a);
        end;
end;

procedure makeroot(a:longint);
begin
    access(a); splay(a); rev[a]:=1;
end;

function getroot(a:longint):longint;
begin
    access(a); splay(a);
    while son[a,1]<>0 do
        begin
            pushdown(a);
            a:=son[a,1];
        end;
    splay(a);
    exit(a);
end;

procedure query(a,b:longint);
begin
    if getroot(a)=getroot(b) then writeln('Yes') else writeln('No');
end;

procedure link(a,b:longint);
begin
    makeroot(a); fa[a]:=b;
end;

procedure cut(a,b:longint);
begin
    makeroot(a); 
    access(b); 
    splay(b); 
    fa[son[b,1]]:=0; 
    son[b,1]:=0;
end;

begin
    readln(n,m);
    for i:=1 to n do
        rev[i]:=0;
    for i:=1 to m do
        begin
            read(cha);
            case cha of
            'Q':begin read(ch,ch,ch,ch); readln(a,b); query(a,b); end;
            'C':begin read(ch,ch,ch,ch,ch,ch); readln(a,b); link(a,b); end;
            'D':begin read(ch,ch,ch,ch,ch,ch); readln(a,b); cut(a,b); end;
            end;
        end;
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值