bzoj 2843 LCT模板

题意:初始n个冰岛独立,三种操作:

(1)判断A、B是否联通,当A、B不联通时输出yes并连接A、B,否则输出no

(2)把点A的点权改为x

(3)判断A、B是否联通,当A、B联通时输出从A到B的路径点权和否则输出impossible

没有cut的LCT基础题...

var
        n,m,x,y         :longint;
        ch              :char;
        s               :string;
        flag            :array[-1..30010] of boolean;
        sum,father,w    :array[-1..30010] of longint;
        son             :array[-1..30010,0..1] of longint;
        i               :longint;
procedure swap(var a,b:Longint);
var
   c:longint;
begin
   c:=a; a:=b; b:=c;
end;

function roott(x:longint):boolean;
begin
   if (son[father[x],0]<>x) and (son[father[x],1]<>x) then exit(true) ;
   exit(false);
end;

procedure update(x:longint);
begin
   sum[x]:=sum[son[x,0]]+sum[son[x,1]]+w[x];
end;

procedure push_down(x:longint);
begin
   if not roott(x) then push_down(father[x]);
   if flag[x] then
   begin
      swap(son[x,0],son[x,1]);
      if son[x,0]<>-1 then flag[son[x,0]]:=not flag[son[x,0]];
      if son[x,1]<>-1 then flag[son[x,1]]:=not flag[son[x,1]];
      flag[x]:=false;
   end;
end;

procedure r_ro(f:longint);
var
    x:longint;
begin
   x:=son[f,0];
   if (son[x,1]<>-1) then father[son[x,1]]:=f;
   son[f,0]:=son[x,1];
   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;
   update(f); update(x);
end;

procedure l_ro(f:longint);
var
        x:longint;
begin
   x:=son[f,1];
   if (son[x,0]<>-1) then father[son[x,0]]:=f;
   son[f,1]:=son[x,0];
   if f=son[father[f],1] then son[father[f],1]:=x
     else if f=son[father[f],0] then son[father[f],0]:=x;
   father[x]:=father[f];
   father[f]:=x;
   son[x,0]:=f;
   update(f); update(x);
end;

procedure splay(x:longint);
begin
   while not roott(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
   y:=-1;
   while x<>0 do
   begin
      push_down(x);
      splay(x);
      son[x,1]:=y;
      update(x);
      y:=x; x:=father[x];
   end;
end;

function find_root(x:longint):longint;
begin
   access(x); splay(x);
   while son[x,0]<>-1 do x:=son[x,0];
   exit(x);
end;

procedure link(x,y:longint);
begin
   access(x); splay(x); flag[x]:=not flag[x];
   access(y); splay(y);
   father[x]:=y;
   son[y,1]:=x;
end;


begin
   read(n);
   for i:=1 to n do read(w[i]);
   for i:=1 to n do sum[i]:=w[i];
   fillchar(son,sizeof(son),255);
   readln(m);
   for i:=1 to m do
   begin
      s:='';
      read(ch);
      while (ch<>' ') do
      begin
         s:=s+ch;
         read(ch);
      end;
      readln(x,y);
      if s='bridge' then
      begin
         if find_root(x)<>find_root(y) then
         begin
            writeln('yes');
            link(x,y);
         end else writeln('no');
      end else
      if s='penguins' then
      begin
         w[x]:=y;
         access(x);
      end else
      begin
         if find_root(x)<>find_root(y) then  writeln('impossible') else
         begin
            access(x);splay(x); flag[x]:=not flag[x];
            access(y);splay(y);
            writeln(sum[y]);
         end;
      end;
   end;
end.
——by Eirlys



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值