[BZOJ 1455]罗马游戏(左偏树+并查集)
Description
罗马皇帝很喜欢玩杀人游戏。 他的军队里面有n个人,每个人都是一个独立的团。最近举行了一次平面几何测试,每个人都得到了一个分数。 皇帝很喜欢平面几何,他对那些得分很低的人嗤之以鼻。他决定玩这样一个游戏。 它可以发两种命令: 1. Merger(i, j)。把i所在的团和j所在的团合并成一个团。如果i, j有一个人是死人,那么就忽略该命令。 2. Kill(i)。把i所在的团里面得分最低的人杀死。如果i这个人已经死了,这条命令就忽略。 皇帝希望他每发布一条kill命令,下面的将军就把被杀的人的分数报上来。(如果这条命令被忽略,那么就报0分)
Solution
比较裸的一道左偏树
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #define MAXN 1000005 using namespace std; int n,m,father[MAXN]; bool die[MAXN]; struct Node { int lch,rch,w,d; Node():lch(0),rch(0),w(0),d(0){} }heap[MAXN]; int merge(int x,int y) { if(!x||!y)return x+y; if(heap[x].w>heap[y].w)swap(x,y); heap[x].rch=merge(y,heap[x].rch); if(heap[heap[x].lch].d<heap[heap[x].rch].d)swap(heap[x].lch,heap[x].rch); heap[x].d=heap[heap[x].rch].d+1; return x; } int find(int x) { if(x==father[x])return x; return father[x]=find(father[x]); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&heap[i].w); father[i]=i;} scanf("%d",&m); for(int i=1;i<=m;i++) { char opt[3];int x,y; scanf("%s",opt); if(opt[0]=='M') { scanf("%d%d",&x,&y); if(die[x]||die[y])continue; int fx=find(x),fy=find(y); if(fx!=fy) father[fx]=father[fy]=merge(fx,fy); } else { scanf("%d",&x); if(die[x])printf("0\n"); else { int fx=find(x); die[fx]=1; printf("%d\n",heap[fx].w); father[fx]=merge(heap[fx].lch,heap[fx].rch); father[father[fx]]=father[fx]; } } } return 0; }