bzoj1455&&luogu2713羅馬遊戲
阿新 • • 發佈:2018-04-20
查詢 ger style space 遊戲 輸入輸出格式 algorithm merger brush
羅馬遊戲
題目描述
羅馬皇帝很喜歡玩殺人遊戲。 他的軍隊裏面有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羅馬遊戲