【以前的空间】BZOJ2733[HNOI2012]永无乡

启发式合并?!

似乎当时写并查集的时候就有看到过类似于把小并查集并到大并查集上的说法,原来这就是启发式……

 

具体做法就是把小树里面的一个个拿出来,然后加到大树里面去(裸的不敢相信)

const

  maxn=300000;

  number=32323231;

var

  left,right,size,value,hash,key,fa,num,root:array[0..maxn]of longint;

  tot:longint;



procedure swap(var x,y:longint);

var

  i:longint;

begin

  i:=x;

  x:=y;

  y:=i;

end;



procedure lt(var x:longint);

var

  k:longint;

begin

  k:=right[x];

  right[x]:=left[k];

  left[k]:=x;

  size[k]:=size[x];

  size[x]:=size[left[x]]+size[right[x]]+1;

  x:=k;

end;



procedure rt(var x:longint);

var

  k:longint;

begin

  k:=left[x];

  left[x]:=right[k];

  right[k]:=x;

  size[k]:=size[x];

  size[x]:=size[left[x]]+size[right[x]]+1;

  x:=k;

end;



procedure insert(var x:longint;y:longint);

begin

  if x=0 then begin

    inc(tot);

    x:=tot;

    value[x]:=num[y];

    hash[x]:=y;

    key[x]:=random(number);

    left[x]:=0;

    right[x]:=0;

    size[x]:=1;

    exit;

  end;

  inc(size[x]);

  if value[x]<num[y] then begin

    insert(right[x],y);

    if key[right[x]]<key[x] then lt(x);

  end

  else begin

    insert(left[x],y);

    if key[left[x]]<key[x] then rt(x);

  end;

end;



procedure dfs(var x:longint;y:longint);

begin

  if y=0 then exit;

  insert(x,hash[y]);

  dfs(x,left[y]);

  dfs(x,right[y]);

end;



function getfa(x:longint):longint;

begin

  if fa[x]=x then exit(x);

  fa[x]:=getfa(fa[x]);

  exit(fa[x]);

end;



procedure link(x,y:longint);

begin

  x:=getfa(x);

  y:=getfa(y);

  if x=y then exit;

  if size[root[x]]<size[root[y]] then swap(x,y);

  dfs(root[x],root[y]);

  fa[y]:=x;

end;



function find(x,y:longint):longint;

begin

  if x=0 then exit(-1);

  if size[left[x]]=y-1 then exit(hash[x]);

  if size[left[x]]>y-1 then exit(find(left[x],y))

    else exit(find(right[x],y-size[left[x]]-1));

end;



procedure into;

var

  i,x,y,n,m:longint;

begin

  readln(n,m);

  randomize;

  for i:=1 to n do begin

    read(num[i]);

    fa[i]:=i;

    insert(root[i],i);

  end;

  for i:=1 to m do begin

    readln(x,y);

    link(x,y);

  end;

end;



procedure work;

var

  n,x,y,i:longint;

  ch:char;

begin

  readln(n);

  for i:=1 to n do begin

    readln(ch,x,y);

    case ch of

      'B':link(x,y);

      'Q':writeln(find(root[getfa(x)],y));

    end;

  end;

end;



begin

  into;

  work;

end.
View Code

 

posted @ 2017-03-02 19:21  Macaulish  阅读(246)  评论(0编辑  收藏  举报