• P3224 [HNOI2012]永无乡


    $ color{#0066ff}{ 题目描述 }$

    永无乡包含 (n) 座岛,编号从 (1)(n) ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 (n) 座岛排名,名次用 (1)(n) 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛到达另一个岛。如果从岛 (a) 出发经过若干座(含 (0) 座)桥可以 到达岛 (b) ,则称岛 (a) 和岛 (b) 是连通的。

    现在有两种操作:

    B x y 表示在岛 (x) 与岛 (y) 之间修建一座新桥。

    Q x k 表示询问当前与岛 (x) 连通的所有岛中第 (k) 重要的是哪座岛,即所有与岛 (x) 连通的岛中重要度排名第 (k) 小的岛是哪座,请你输出那个岛的编号。

    (color{#0066ff}{输入格式})

    第一行是用空格隔开的两个正整数 (n)(m) ,分别表示岛的个数以及一开始存在的桥数。

    接下来的一行是用空格隔开的 (n) 个数,依次描述从岛 (1) 到岛 (n) 的重要度排名。随后的 (m) 行每行是用空格隔开的两个正整数 (a_i)(b_i) ,表示一开始就存在一座连接岛 (a_i) 和岛 (b_i) 的桥。

    后面剩下的部分描述操作,该部分的第一行是一个正整数 (q) ,表示一共有 (q) 个操作,接下来的 (q) 行依次描述每个操作,操作的 格式如上所述,以大写字母 (Q)(B) 开始,后面跟两个不超过 (n) 的正整数,字母与数字以及两个数字之间用空格隔开。

    (color{#0066ff}{输出格式})

    对于每个 Q x k 操作都要依次输出一行,其中包含一个整数,表示所询问岛屿的编号。如果该岛屿不存在,则输出(-1)

    (color{#0066ff}{输入样例})

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

    (color{#0066ff}{输出样例})

    -1
    2
    5
    1
    2
    

    (color{#0066ff}{数据范围与提示})

    对于 20% 的数据 (n leq 1000, q leq 1000)

    对于 100% 的数据 (n leq 100000, m leq n, q leq 300000)

    (color{#0066ff}{题解})

    B操作,平衡树暴力合并,因为最多(logn)次,所以没毛病

    Q操作,Splay的kth就行

    注意插入的时候要保证为根,先splay上去!

    然而不splay上去也能A,数据水

    #include<bits/stdc++.h>
    #define LL long long
    LL in() {
    	char ch; LL x = 0, f = 1;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    	return x * f;
    }
    const int maxn = 3e5 + 10;
    int n, m;
    struct Splay {
    protected:
    	struct node {
    		node *ch[2], *fa;
    		int val, siz;
    		node(int val = 0, int siz = 0): val(val), siz(siz) { fa = ch[0] = ch[1] = NULL; }
    		void upd() { siz = (ch[0]? ch[0]->siz : 0) + (ch[1]? ch[1]->siz : 0) + 1; }
    		int rk() { return ch[0]? ch[0]->siz + 1 : 1; }
    		bool isr() { return this == fa->ch[1]; }
    		void clr() {
    			siz = 1;
    			if(ch[0]) ch[0]->fa = NULL;
    			if(ch[1]) ch[1]->fa = NULL;
    			if(fa) fa->ch[val > fa->val] = NULL;
    			fa = ch[0] = ch[1] = NULL;
    		}
    	}pool[maxn];
    	void rot(node *x) {
    		node *y = x->fa, *z = y->fa;
    		bool k = x->isr(); node *w = x->ch[!k];
    		if(z) z->ch[y->isr()] = x;
    		(x->ch[!k] = y)->ch[k] = w;
    		(y->fa = x)->fa = z;
    		if(w) w->fa = y;
    		y->upd(), x->upd();
    	}
    	void splay(node *o) {
    		while(o->fa) {
    			if(o->fa->fa) rot(o->isr() ^ o->fa->isr()? o : o->fa);
    			rot(o);
    		}
    	}
    	int kth(node *o, int k) {
    		splay(o);
    		if(o->siz < k) return -1;
    		while(o && o->rk() != k) {
    			if(o->rk() > k) o = o->ch[0];
    			else k -= o->rk(), o = o->ch[1];
    		}
    		return o - pool;
    	}
    	void ins(node *rt, node *o) {
    		splay(rt);
    		o->clr();
    		node *now = rt, *fa = NULL;
    		while(now) fa = now, now = now->ch[o->val > now->val];
    		o->fa = fa;
    		fa->ch[o->val > fa->val] = o;
    		splay(o);
    	}
    
    	void dfs(node *o, node *rt) {
    		if(o->ch[0]) dfs(o->ch[0], rt);
    		if(o->ch[1]) dfs(o->ch[1], rt);
    		ins(rt, o);
    	}
    	node *findroot(node *o) { while(o->fa) o = o->fa; return o; }
    	void outtree(node *o) {
    		if(o->ch[0]) outtree(o->ch[0]);
    		if(o->ch[1]) outtree(o->ch[1]);
    	}
    public:
    	void init(int *val, int n) { for(int i = 1; i <= n; i++) pool[i] = node(val[i], 1); }
    	void link(int x, int y) {
    		node *a = pool + x, *b = pool + y;
    		if(findroot(a) == findroot(b)) return;
    		splay(a), splay(b);
    		dfs(a, b);
    	}
    	int query(int x, int k) { return kth(pool + x, k); }
    }s;
    int val[maxn];
    char getch() {
    	char ch;
    	while(!isalpha(ch = getchar()));
    	return ch;
    }
    
    int main() {
    	n = in(), m = in();
    	for(int i = 1; i <= n; i++) val[i] = in();
    	s.init(val, n);
    	int x, y;
    	for(int i = 1; i <= m; i++) x = in(), y = in(), s.link(x, y);
    	for(int T = in(); T --> 0;) {
    		if(getch() == 'Q') {
    			x = in(), y = in();
    			printf("%d
    ", s.query(x, y));
    		} else {
    			x = in(), y = in();
    			s.link(x, y);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    UML画图
    UML笔记
    电脑启动顺序
    评教有感
    部署图
    活动图
    给八期授课之主板电池的思考
    给八期授课之人员分配的思考
    构件图
    cocos2dx获得机器语言
  • 原文地址:https://www.cnblogs.com/olinr/p/10434988.html
Copyright © 2020-2023  润新知