【洛谷 P3224】 [HNOI2012]永无乡(Splay,启发式合并)
题目链接
启发式合并就是暴力合并把小的合并到大的里,一个一个插进去。
并查集维护连通性,同时保证并查集的根就是所在Splay的根,这样能省去很多操作。
#include <cstdio>
#include <algorithm>
using namespace std;
inline int read(){
int s = 0, w = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-')w = -1;ch = getchar();}
while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0',ch = getchar();
return s * w;
}
const int MAXN = 100010;
struct SplayTree{
int ch[2], fa, val, size;
}t[MAXN];
int num, root, n, m, f[MAXN];
int find(int x){
return f[x] == x ? x : f[x] = find(f[x]);
}
void pushup(int u){
t[u].size = t[t[u].ch[0]].size + t[t[u].ch[1]].size + 1;
}
void rotate(int x){
int y = t[x].fa;
int z = t[y].fa;
int k = t[y].ch[1] == x;
t[z].ch[t[z].ch[1] == y] = x;
t[x].fa = z;
t[y].ch[k] = t[x].ch[k ^ 1];
t[t[x].ch[k ^ 1]].fa = y;
t[x].ch[k ^ 1] = y;
t[y].fa = x;
pushup(y);
pushup(x);
}
void Splay(int x, int goal){
while(t[x].fa){
int y = t[x].fa, z = t[y].fa;
if(z)
/**/ (t[z].ch[0] == y) ^ (t[y].ch[0] == x) ? rotate(x) : rotate(y);
rotate(x);
}
if(goal == 0) root = x;
}
inline int findKth(int k){
int u = root;
while(1){
if(t[t[u].ch[0]].size >= k) u = t[u].ch[0];
else if(t[t[u].ch[0]].size == k - 1) return u;
else k -= t[t[u].ch[0]].size + 1, u = t[u].ch[1];
}
}
int next(int x, int mode){
int u = t[x].ch[mode];
while(t[u].ch[!mode]) u = t[u].ch[!mode];
return u;
}
int a, b;
char c;
void insert(int x){
int u = root, fa = 0;
while(u) fa = u, u = t[u].ch[t[x].val > t[u].val];
t[fa].ch[t[x].val > t[fa].val] = x;
t[x].fa = fa;
Splay(x, 1);
}
void merge(int u){
if(t[u].ch[0]) merge(t[u].ch[0]);
if(t[u].ch[1]) merge(t[u].ch[1]);
t[u].ch[0] = t[u].ch[1] = 0; insert(u);
}
int T;
int main(){
n = read(); m = read();
for(int i = 1; i <= n; ++i)
t[i].val = read(), t[i].size = 1, f[i] = i;
for(int i = 1; i <= m; ++i){
a = read(); b = read();
int x = find(a), y = find(b);
if(x == y) continue;
if(t[x].size > t[y].size){
f[y] = x;
root = x; merge(y); Splay(x, 0);
}
else{
f[x] = y;
root = y; merge(x); Splay(y, 0);
}
}
T = read();
for(int i = 1; i <= T; ++i){
c = getchar(); while(c != 'Q' && c != 'B') c = getchar();
a = read(); b = read();
if(c == 'B'){
int x = find(a), y = find(b);
if(x == y) continue;
if(t[x].size > t[y].size){
f[y] = x;
root = x; merge(y); Splay(x, 0);
}
else{
f[x] = y;
root = y; merge(x); Splay(y, 0);
}
}
else{
root = find(a);
if(t[root].size < b) printf("%d\n", -1);
else printf("%d\n", findKth(b));
}
}
return 0;
}
【洛谷 P3224】 [HNOI2012]永无乡(Splay,启发式合并)的更多相关文章
- 洛谷.3224.[HNOI2012]永无乡(Splay启发式合并)
题目链接 查找排名为k的数用平衡树 合并时用启发式合并,把size小的树上的所有节点插入到size大的树中,每个节点最多需要O(logn)时间 并查集维护连通关系即可 O(nlogn*insert t ...
- 洛谷P3224 [HNOI2012]永无乡(线段树合并+并查集)
题目描述 永无乡包含 nnn 座岛,编号从 111 到 nnn ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 nnn 座岛排名,名次用 111 到 nnn 来表示.某些岛之间由巨大的桥连接, ...
- 洛谷 P3224 [HNOI2012]永无乡 解题报告
P3224 [HNOI2012]永无乡 题目描述 永无乡包含 \(n\) 座岛,编号从 \(1\) 到 \(n\) ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 \(n\) 座岛排名,名次用 ...
- BZOJ 2733: [HNOI2012]永无乡 [splay启发式合并]
2733: [HNOI2012]永无乡 题意:加边,询问一个连通块中k小值 终于写了一下splay启发式合并 本题直接splay上一个节点对应图上一个点就可以了 并查集维护连通性 合并的时候,把siz ...
- 洛谷 P3224 [HNOI2012]永无乡
题面 永无乡包含 \(n\) 座岛,编号从 \(1\) 到 \(n\) ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 \(n\) 座岛排名,名次用 \(1\) 到 \(n\) 来表示.某些岛 ...
- [BZOJ2733] [HNOI2012] 永无乡 (splay启发式合并)
Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以 ...
- 【洛谷3224/BZOJ2733】[HNOI2012]永无乡 (Splay启发式合并)
题目: 洛谷3224 分析: 这题一看\(n\leq100000\)的范围就知道可以暴力地用\(O(nlogn)\)数据结构乱搞啊-- 每个联通块建一棵Splay树,查询就是Splay查询第k大的模板 ...
- [洛谷P3224][HNOI2012]永无乡
题目大意:给你$n$个点,每个点有权值$k$,现有两种操作: 1. $B\;x\;y:$将$x,y$所在联通块合并2. $Q\;x\;k:$查询第$x$个点所在联通块权值第$k$小是哪个数 题解:线段 ...
- 2018.08.11 洛谷P3224 [HNOI2012]永无乡(线段树合并)
传送门 给出n个带点权的点,支持连边和查询连通块第k大. 这个貌似就是一道线段树合并的裸板啊... 代码: #include<bits/stdc++.h> #define N 100005 ...
- 【BZOJ-2733】永无乡 Splay+启发式合并
2733: [HNOI2012]永无乡 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2048 Solved: 1078[Submit][Statu ...
随机推荐
- windows 共享文件夹
windows 共享文件夹 同步工作组 右键单击"计算机",选择"属性" 更改设置 单击"更改". 输入工作组 和 主机名 启计算机使更改生 ...
- Swarm容器集群管理(超详细)
一.Swarm介绍 Swarm是Docker公司自研发的容器集群管理系统, Swarm在早期是作为一个独立服务存在, 在Docker Engine v1.12中集成了Swarm的集群管理和编排功能.可 ...
- hadoop大作业
1.数据准备 2.把CSV添加到/bigdatacase/dataset中 3.检查前5行并删除第一行 4.将csv文件导入hadoop并检查前10行数据情况 5.数据文件导入hive 6.在Hive ...
- 第06组 Beta冲刺(2/5)
队名:拾光组 组长博客链接 作业博客链接 团队项目情况 燃尽图(组内共享) 组长:宋奕 过去两天完成了哪些任务 维护后端代码 学习后端架构 GitHub签入记录 接下来的计划 维护后端代码,跟进组员完 ...
- Linux:读取文件,每行拆分,并比较拆分数组长度
读取文件,每行拆分,并比较拆分数组长度 #!/bin/bash FILENAME=./.txt function While_read_LINE(){ cat $FILENAME | while re ...
- Python常用模块大全
Python常用模块大全 os模块: os.remove() 删除文件 os.unlink() 删除文件 os.rename() 重命名文件 os.listdir() 列出指定目录下所有文件 os.c ...
- 更新Alpine Linux源 sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories apk add xxx
更新Alpine Linux源 国内镜像源 清华TUNA镜像源:https://mirror.tuna.tsinghua.edu.cn/alpine/中科大镜像源:http://mirrors.ust ...
- mysql 5.6配置
简洁版: [client] port = 3306 socket = /weyeedata/mysql/run/mysql.sock [mysqld] innodb_buffer_pool_size ...
- python离线包下载地址
https://pypi.org/project/pdfconv/ https://pypi.org/search/?q=major&o=
- 阮一峰的ES6---Promise对象
https://www.imooc.com/article/20580?block_id=tuijian_wz Promise的含义promise是异步编程的一种解决方法,比传统的回调函数和事件更合理 ...