bzoj 1455
题意:n个人,每个人有一个分数,每个人都是一个独立的团,有两种操作:
1、M x y,在x和y都是活的前提下,把x所在团和y所在团合并,否则忽略此操作
2、K x 在x是活的的前提下,把x所在团分数最小的人杀死,并输出该人分数,若x已经死亡则输出0
显然,用并查集维护团的信息,每次只删除分数最小的人,并涉及合并,妥妥的左偏树模板
var
n,m,x,y,tx,ty,root:longint;
i :longint;
ch :char;
f,sco,l,r,dis :array[0..1000010] of longint;
flag :array[0..1000010] of boolean;
procedure swap(var a,b:longint);
var
c:longint;
begin
c:=a; a:=b; b:=c;
end;
function get_father(x:longint):longint;
begin
if x=f[x] then exit(x);
f[x]:=get_father(f[x]);
exit(f[x]);
end;
function merge(a,b:longint):longint;
begin
if (a=0) or (b=0) then exit(a+b);
if sco[a]>sco[b] then swap(a,b);
r[a]:=merge(r[a],b);
if dis[l[a]]<dis[r[b]] then swap(l[a],r[a]);
dis[a]:=dis[r[a]]+1;
exit(a);
end;
begin
read(n);
for i:=1 to n do read(sco[i]);
for i:=1 to n do f[i]:=i;
readln(m);
for i:=1 to m do
begin
read(ch);
if ch='K' then
begin
readln(x);
if flag[x] then writeln(0) else
begin
tx:=get_father(x);
writeln(sco[tx]);
flag[tx]:=true;
f[tx]:=merge(l[tx],r[tx]);
f[f[tx]]:=f[tx];
end;
end else
begin
readln(x,y);
if not flag[x] and not flag[y] then
begin
tx:=get_father(x);
ty:=get_father(y);
if (tx<>ty) then
begin
root:=merge(tx,ty);
f[tx]:=root;
f[ty]:=root;
end;
end;
end;
end;
end.
洛谷 P3377 题意同上
#include<stdio.h>
#include<string.h>
int key[100010], l[100010], r[100010], dis[100010];
int father[100010], flag[100010];
void swap(int *a, int *b) {
int c;
c = *a;
*a = *b;
*b = c;
}
int get_father(int x) {
if (x == father[x]) return(father[x]);
father[x] = get_father(father[x]);
return(father[x]);
}
int merge(int a, int b) {
if ((a == 0) || (b == 0)) return(a + b);
if (key[a] > key[b]) swap(&a, &b);
r[a] = merge(r[a], b);
if (dis[l[a]] < dis[r[a]]) swap(&l[a], &r[a]);
dis[a] = dis[r[a]] + 1;
return(a);
}
int main() {
int n, m, t;
int i;
int x, y, tx, ty;
memset(l, 0, sizeof(l));
memset(r, 0, sizeof(r));
memset(flag, 0, sizeof(flag));
scanf("%d %d", &n, &m);
for (i = 1; i <= n ; i++) {
father[i] = i;
scanf("%d", &key[i]);
}
for (i = 1; i <= m ; i++) {
scanf("%d", &t);
if (t == 1) {
scanf("%d %d", &x, &y);
if ((flag[x] == 0) && (flag[y] == 0)){
tx = get_father(x);
ty = get_father(y);
if (tx != ty)
father[tx] = father[ty] = merge(tx, ty);
}
} else {
scanf("%d", &x);
if (flag[x] != 0) printf("-1\n"); else {
tx = get_father(x);
printf("%d\n", key[tx]);
flag[tx] = 1;
father[father[tx]]= father[tx] = merge(l[tx], r[tx]);
}
}
}
}
—— by Eirlys