国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

【Bzoj2733】永無鄉(xiāng)

2019-11-10 19:40:18
字體:
供稿:網(wǎng)友

2733: [HNOI2012]永無鄉(xiāng)

Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3031  Solved: 1592[Submit][Status][Discuss]

Description

永無鄉(xiāng)包含 n 座島,編號從 1 到 n,每座島都有自己的獨(dú)一無二的重要度,按照重要度可 以將這 n 座島排名,名次用 1 到 n 來表示。某些島之間由巨大的橋連接,通過橋可以從一個島 到達(dá)另一個島。如果從島 a 出發(fā)經(jīng)過若干座(含 0 座)橋可以到達(dá)島 b,則稱島 a 和島 b 是連 通的。現(xiàn)在有兩種操作:B x y 表示在島 x 與島 y 之間修建一座新橋。Q x k 表示詢問當(dāng)前與島 x連通的所有島中第 k 重要的是哪座島,即所有與島 x 連通的島中重要度排名第 k 小的島是哪 座,請你輸出那個島的編號。  

Input

輸入文件第一行是用空格隔開的兩個正整數(shù) n 和 m,分別 表示島的個數(shù)以及一開始存在的橋數(shù)。接下來的一行是用空格隔開的 n 個數(shù),依次描述從島 1 到島 n 的重要度排名。隨后的 m 行每行是用空格隔開的兩個正整數(shù) ai 和 bi,表示一開始就存 在一座連接島 ai 和島 bi 的橋。后面剩下的部分描述操作,該部分的第一行是一個正整數(shù) q, 表示一共有 q 個操作,接下來的 q 行依次描述每個操作,操作的格式如上所述,以大寫字母 Q 或B 開始,后面跟兩個不超過 n 的正整數(shù),字母與數(shù)字以及兩個數(shù)字之間用空格隔開。 對于 20%的數(shù)據(jù) n≤1000,q≤1000  對于 100%的數(shù)據(jù) n≤100000,m≤n,q≤300000  

Output

對于每個 Q x k 操作都要依次輸出一行,其中包含一個整數(shù),表 示所詢問島嶼的編號。如果該島嶼不存在,則輸出-1。  

Sample Input

5 14 3 2 5 1 1 2 7Q 3 2 Q 2 1 B 2 3 B 1 5 Q 2 1 Q 2 4 Q 2 3

Sample Output

-12512

算法:平衡樹啟發(fā)式合并。心力交瘁的渣羊er出現(xiàn)了,自從昨天說HNOI好水之后遭報應(yīng),碰到了一道想死的題(神犇們不要鄙視,本人水平有限,雖然在你們是一眼題QwQ)。咳咳,看很多人都是并查集維護(hù)連通塊,每個連通塊內(nèi)建一個權(quán)值線段樹(可以查排名的那種),然后只用維護(hù)合并與查詢就行。但還是基于水平原因,Zhayan9決定還是用Treap+啟發(fā)式合并水過...代碼也有點(diǎn)玄學(xué),還是貼過來吧...
#include <cstdio>#include <algorithm>#include <iostream>using namespace std;const int maxx = 100000 + 100;int n,m,x,y,root,t;int father[maxx];char flag[2];struct Node{	int lc,rc;	int v,fix;	int size;}T[maxx];inline int read(){    int x=0,f=1;char c=getchar();    while(c>'9'||c<'0') {if(c == '-') f=-1; c=getchar();}    while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}    return x*f;}void update(int i){    T[i].size = T[T[i].lc].size + T[T[i].rc].size + 1;}void lturn(int &i){    int t = T[i].rc;    T[i].rc = T[t].lc;    T[t].lc = i;    T[t].size = T[i].size;    update(i);    i = t;}void rturn(int &i){    int t = T[i].lc;    T[i].lc = T[t].rc;    T[t].rc = i;    T[t].size = T[i].size;    update(i);    i = t;}void insert(int &i,int x){    if(i == 0){		i = x;		T[i].size = 1;		T[i].lc = T[i].rc = 0;		T[i].fix = rand();		return;    }    T[i].size++;    if(T[x].v < T[i].v){		insert(T[i].lc,x);		if(T[T[i].lc].fix < T[i].fix) rturn(i);	}    if(T[x].v > T[i].v){		insert(T[i].rc,x);		if(T[T[i].rc].fix < T[i].fix) lturn(i);	}}int Query_num(int i,int x){    int rank = T[T[i].lc].size;    if(rank+1 == x) return i;    else if(rank >= x) return Query_num(T[i].lc,x);    else return Query_num(T[i].rc,x-rank-1);}int find(int x){	if(father[x]!=x) father[x] = find(father[x]);    return father[x]; }void merge(int x,int y){	if(y == 0) return;	merge(x,T[y].lc);	merge(x,T[y].rc);	insert(x,y);}void unionn(int x,int y){	int r1=find(x),r2=find(y);	if(T[r1].size > T[r2].size) x^=y^=x^=y;	father[r1]=r2;	merge(r2,r1);} int main(){	n = read();m = read();	for(int i=1;i<=n;i++)		T[i].v = read(),T[i].size = 1,father[i] = i;	for(int i=1;i<=m;i++)		x = read(),y = read(),unionn(x,y);	t = read();	while( t-- ){		scanf("%s",flag);		x = read();y = read();		if(flag[0] == 'B') unionn(x,y);		else{			int fx = find(x);			if(T[fx].size < y) PRintf("-1/n");			else printf("%d/n",Query_num(fx,y));		}	}	return 0;}
發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 闸北区| 富顺县| 厦门市| 黄陵县| 安陆市| 中方县| 昌图县| 昆明市| 射洪县| 楚雄市| 日土县| 钦州市| 鹰潭市| 台州市| 延长县| 尉氏县| 集安市| 柳林县| 福海县| 东莞市| 顺平县| 信阳市| 留坝县| 万年县| 阳江市| 米脂县| 玉门市| 务川| 大名县| 关岭| 晴隆县| 青海省| 海林市| 杭锦旗| 萨迦县| 磐石市| 渑池县| 福清市| 呼和浩特市| 平陆县| 原阳县|