学习了一下可合并堆的一种写法——左偏树
感觉左偏树是一种类似启发式的方法
学习左偏树后这题就水过去了
1 var fa,l,r,a,d:array[0..1000010] of longint; 2 v:array[0..1000010] of boolean; 3 i,n,m,x,y,f:longint; 4 ch:char; 5 6 function getf(x:longint):longint; 7 begin 8 if fa[x]<>x then fa[x]:=getf(fa[x]); 9 exit(fa[x]); 10 end; 11 12 procedure swap(var a,b:longint); 13 var c:longint; 14 begin 15 c:=a; 16 a:=b; 17 b:=c; 18 end; 19 20 function merge(x,y:longint):longint; 21 begin 22 if x=0 then exit(y); 23 if y=0 then exit(x); 24 if a[x]>a[y] then swap(x,y); 25 r[x]:=merge(r[x],y); 26 if d[r[x]]>d[l[x]] then swap(l[x],r[x]); 27 d[x]:=d[r[x]]+1; //d表示这个节点到最近的可插入节点的距离,根据左偏树性质易得 28 exit(x); 29 end; 30 31 begin 32 readln(n); 33 for i:=1 to n do 34 begin 35 read(a[i]); 36 fa[i]:=i; 37 end; 38 d[0]:=-1; 39 readln(m); 40 for i:=1 to m do 41 begin 42 read(ch); 43 if ch='M' then 44 begin 45 readln(x,y); 46 if v[x] or v[y] then continue; 47 x:=getf(x); 48 y:=getf(y); 49 if x=y then continue; 50 f:=merge(x,y); 51 fa[x]:=f; 52 fa[y]:=f; 53 end 54 else begin 55 readln(x); 56 if v[x] then 57 begin 58 writeln(0); 59 continue; 60 end; 61 x:=getf(x); 62 v[x]:=true; 63 writeln(a[x]); 64 fa[x]:=merge(l[x],r[x]); 65 fa[fa[x]]:=fa[x]; 66 end; 67 end; 68 end. 69 70