Description
罗马皇帝很喜欢玩杀人游戏。 他的军队里面有n个人,每个人都是一个独立的团。最近举行了一次平面几何测试,每个人都得到了一个分数。 皇帝很喜欢平面几何,他对那些得分很低的人嗤之以鼻。他决定玩这样一个游戏。 它可以发两种命令: 1. Merger(i, j)。把i所在的团和j所在的团合并成一个团。如果i, j有一个人是死人,那么就忽略该命令。 2. Kill(i)。把i所在的团里面得分最低的人杀死。如果i这个人已经死了,这条命令就忽略。 皇帝希望他每发布一条kill命令,下面的将军就把被杀的人的分数报上来。(如果这条命令被忽略,那么就报0分)
【题目分析】
可并堆–左偏树
【代码】
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int fa[1000001],v[1000001],die[1000001],n,q,l[1000001],r[1000001],d[1000001];
char opt[11];
inline int gf(int k)
{
if (fa[k]==k) return k;
else return fa[k]=gf(fa[k]);
}
inline int merge(int x,int y)
{
if (!x||!y) return x+y;
if (v[x]>v[y]) swap(x,y);
r[x]=merge(r[x],y);
if (d[l[x]]<d[r[x]]) swap(l[x],r[x]);
d[x]=d[r[x]]+1;
return x;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;++i) scanf("%d",&v[i]),fa[i]=i;
scanf("%d",&q);
while (q--)
{
scanf("%s",opt);
if (opt[0]=='M')
{
int x,y;
scanf("%d%d",&x,&y);
if (die[x]||die[y]) continue;
int fx=gf(x),fy=gf(y);
if (fx!=fy) fa[fx]=fa[fy]=merge(fx,fy);
}
else
{
int x;
scanf("%d",&x);
if (die[x])
{
printf("0\n");
continue;
}
else
{
int fx=gf(x);
die[fx]=1;
printf("%d\n",v[fx]);
int tmp=merge(l[fx],r[fx]);
fa[fx]=fa[tmp]=tmp;
}
}
}
}