bzoj1455&&luogu2713罗马游戏
Posted 时间飞逝
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1455&&luogu2713罗马游戏相关的知识,希望对你有一定的参考价值。
罗马游戏
题目描述
罗马皇帝很喜欢玩杀人游戏。 他的军队里面有n个人,每个人都是一个独立的团。最近举行了一次平面几何测试,每个人都得到了一个分数。 皇帝很喜欢平面几何,他对那些得分很低的人嗤之以鼻。
他决定玩这样一个游戏。 它可以发两种命令:
- Merger(i, j)。把i所在的团和j所在的团合并成一个团。如果i, j有一个人是死人,那么就忽略该命令。
-
Kill(i)。把i所在的团里面得分最低的人杀死。如果i这个人已经死了,这条命令就忽略。
皇帝希望他每发布一条kill命令,下面的将军就把被杀的人的分数报上来。(如果这条命令被忽略,那么就报0分)
输入输出格式
输入格式:
第一行一个整数n(1<=n<=1000000)。n表示士兵数,m表示总命令数。
第二行n个整数,其中第i个数表示编号为i的士兵的分数。(分数都是[0..10000]之间的整数)
第三行一个整数m(1<=m<=100000) 第3+i行描述第i条命令。命令为如下两种形式: 1. M i j 2. K i
输出格式:
如果命令是Kill,对应的请输出被杀人的分数。(如果这个人不存在,就输出0)
输入输出样例
输入样例: 5 100 90 66 99 10 7 M 1 5 K 1 K 1 M 2 3 M 3 4 K 5 K 4
输出样例: 10 100 0 66
分析:很明显这是一道可并堆的经典题目,题目字面翻译过来就是合并小根堆,并且查询最小值后删除最小值,比较简单,类似于板子题。
#include <stdio.h> #include <algorithm> using namespace std; int dis[1000001]; int num[1000001]; int son[1000001][2]; int fa[1000001]; bool kill[1000001]; int n,m; int find(int p) { if(fa[p]==0) return 0; return (fa[p]==p)?p:fa[p]=find(fa[p]); } int merge(int x,int y) { if(!x) return y; if(!y) return x; if(num[x]>num[y]) swap(x,y); son[x][1]=merge(son[x][1],y); if(dis[son[x][1]]>dis[son[x][0]]) swap(son[x][1],son[x][0]); dis[x]=dis[son[x][1]]+1; return x; } int main() { dis[0]=-1; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&num[i]),fa[i]=i; scanf("%d",&m); for(int i=1;i<=m;i++) { int a,b; char kind[2]; scanf("%s",kind); if(kind[0]==‘M‘) { scanf("%d%d",&a,&b); if(kill[a]||kill[b]) continue; a=find(a),b=find(b); if(a!=b) fa[a]=fa[b]=merge(a,b); } else { scanf("%d",&a); if(kill[a]) { printf("0\n"); continue; } int rt; printf("%d\n",num[rt=find(a)]); kill[rt]=true; b=son[rt][0],a=son[rt][1]; fa[rt]=fa[a]=fa[b]=merge(a,b); } } }
以上是关于bzoj1455&&luogu2713罗马游戏的主要内容,如果未能解决你的问题,请参考以下文章
Bzoj-2002&&Luogu-3203&CodeVS-2333