【洛谷P3224】永无乡 并查集+Splay启发式合并
题目大意:给定 N 个点的图,点有点权,初始有一些无向边,现在有 Q 个询问,每个询问支持动态增加一条无向边连接两个不连通的点和查询第 X 个点所在的联通块中权值第 K 大的是哪个点。
题解:学会了平衡树的启发式合并。
以每个点建立一棵平衡树,需要加边时则合并两个点对应的平衡树,启发式的思想在于合并的时候将 size 小的平衡树信息合并到 size 大的树上。这样,对于每一个被合并的点来说,其所在的平衡树的大小必定翻倍,而最极端的话,所有的点都在一个平衡树中,size = n,因此,每个点被合并的次数不超过 \(O(logn)\) 次,即:新建的节点数不超过 \(O(nlogn)\) 个。
需要注意的是,对于 Splay 来说,若对于以前的单个平衡树来说,根节点的父节点可以取 0,但是有 N 棵平衡树的话,每棵平衡树根节点的父节点不能相同,因此,将 tot 初始化成 N,对于第 i 个平衡树的根节点,将 i 作为其父节点,并且根节点需要手动初始化,不能 insert。
连通性什么的直接并查集维护就好喽。
代码如下
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n,m,q,f[maxn],mp[maxn];
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
struct node{
#define ls(x) t[x].ch[0]
#define rs(x) t[x].ch[1]
int ch[2],fa,val,size;
}t[maxn<<3];
int tot,root[maxn];
inline void pushup(int o){t[o].size=t[ls(o)].size+t[rs(o)].size+1;}
inline bool get(int o){return o==rs(t[o].fa);}
inline void rotate(int o){
int fa=t[o].fa,gfa=t[fa].fa;
int d1=get(o),d2=get(fa);
t[fa].ch[d1]=t[o].ch[d1^1],t[t[o].ch[d1^1]].fa=fa;
t[fa].fa=o,t[o].ch[d1^1]=fa;
t[gfa].ch[d2]=o,t[o].fa=gfa;
pushup(fa),pushup(o);
}
inline void splay(int o,int goal){
while(t[o].fa!=goal){
int fa=t[o].fa,gfa=t[fa].fa;
if(gfa!=goal)get(o)==get(fa)?rotate(fa):rotate(o);
rotate(o);
}
if(goal<=n)root[goal]=o;
}
void insert(int val,int i){
int o=root[i],fa=0;
while(o)fa=o,o=t[o].ch[t[o].val<val];
o=++tot;
if(fa)t[fa].ch[t[fa].val<val]=o;
t[o].fa=fa,t[o].val=val,t[o].size=1;
splay(o,i);
}
int kth(int o,int k){
if(k<=t[ls(o)].size)return kth(ls(o),k);
else if(k>t[ls(o)].size+1)return kth(rs(o),k-t[ls(o)].size-1);
else return t[o].val;
}
void dfs(int o,int i){
if(ls(o))dfs(ls(o),i);
if(rs(o))dfs(rs(o),i);
insert(t[o].val,i);
}
void merge(int a,int b){
if(!a||!b)return;
int x=find(a),y=find(b);
if(x==y)return;
if(t[root[x]].size>t[root[y]].size)swap(x,y);
f[x]=y;
dfs(root[x],y);
}
void read_and_parse(){
scanf("%d%d",&n,&m),tot=n;
for(int i=1,val;i<=n;i++){
scanf("%d",&val);
f[i]=i,mp[val]=i;
root[i]=++tot,t[root[i]].fa=i,t[root[i]].size=1,t[root[i]].val=val;
}
for(int i=1,a,b;i<=m;i++){
scanf("%d%d",&a,&b);
merge(a,b);
}
}
void solve(){
char opt[2];int x,y;
scanf("%d",&q);
while(q--){
scanf("%s%d%d",opt,&x,&y);
if(opt[0]=='B')merge(x,y);
else{
if(y>t[root[find(x)]].size)puts("-1");
else printf("%d\n",mp[kth(root[find(x)],y)]);
}
}
}
int main(){
read_and_parse();
solve();
return 0;
}
【洛谷P3224】永无乡 并查集+Splay启发式合并的更多相关文章
- 洛谷P3224 永无乡 [HNOI2012] 线段树/splay/treap
正解:线段树合并 解题报告: 传送门! 这题也是有很多解法,eg:splay,treap,... 然而我都不会我会学的QAQ! 反正今天就只讲下线段树合并怎么做QAQ 首先看到这样子的说第k重要的是什 ...
- BZOJ2733 [HNOI2012]永无乡(并查集+线段树合并)
题目大意: 在$n$个带权点上维护两个操作: 1)在点$u,v$间连一条边: 2)询问点$u$所在联通块中权值第$k$小的点的编号,若该联通块中的点的数目小于$k$,则输出$-1$: 传送门 上周的模 ...
- 洛谷 [P3224] 永无乡
Treap 的合并 首先感谢 @Capella 的DeBug 其次,这是由一个 & 号引发的血案 注意对于所有修改操作都要 & Treap的合并, 启发式合并,对于每一个节点都 ins ...
- bzoj 2733 永无乡 - 并查集 - 线段树
永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛. ...
- BZOJ 2733 [HNOI2012]永无乡 (权值线段树启发式合并+并查集)
题意: n<=1e5的图里,在线连边.查询某连通块第k大 思路: 练习线段树合并的好题,因为依然记得上一次启发式合并trie的时候内存爆炸的恐怖,所以这次还是用了动态开点.回收 听说启发式合并s ...
- 【BZOJ2733】永无乡(线段树,启发式合并)
题意:支持合并,求块内K小数 对于 100%的数据 n≤100000,m≤n,q≤300000 思路:对于每一个块建立一棵动态开点的线段树,暴力(启发式?)合并后二分下就行了 merge用函数的方式写 ...
- B20J_2733_[HNOI2012]永无乡_权值线段树合并
B20J_2733_[HNOI2012]永无乡_权值线段树合并 Description:n座岛,编号从1到n,每座岛都有自己的独一无二的重要度,按照重要度可以将这n座岛排名,名次用1到 n来表示.某些 ...
- 洛谷P1525 关押罪犯(并查集、二分图判定)
本人蒟蒻,只能靠题解AC,看到大佬们的解题思路,%%%%%% https://www.luogu.org/problemnew/show/P1525 题目描述 S城现有两座监狱,一共关押着N名罪犯,编 ...
- Bzoj1015/洛谷P1197 [JSOI2008]星球大战(并查集)
题面 Bzoj 洛谷 题解 考虑离线做法,逆序处理,一个一个星球的加入.用并查集维护一下连通性就好了. 具体来说,先将被消灭的星球储存下来,先将没有被消灭的星球用并查集并在一起,这样做可以路径压缩,然 ...
随机推荐
- iphone忘记锁屏密码却记得appleID密码的不保存数据的刷机办法
请注意看清题目再看本文,另外一切后果博主不负任何责任.操作实现环境:原装数据线,拔掉sim卡昨天,iPhone6sp忘记密码被锁定,尝试通过找回手机抹除手机功能后,提示需要手机接入互联网才能实现,而我 ...
- 挂载银行前置机Ukey到windows server2012虚拟机的操作记录
公司有跟银行对接的金融业务,需要配置银行前置机环境.通过KVM的WebVirtMgr管理平台创建windows server2008虚拟机,安装参考:kvm虚拟化管理平台WebVirtMgr部署-完整 ...
- 《Linux内核设计与分析》第十七章读书笔记
设备与模块 关于设备驱动和设备管理,四种内核成分. 设备类型:在所有Unix 系统中为了统一普通设备的操作所采用的分类. 模块: Linux 内核中用于按需加载和卸载目标码的机制. 内核对象:内核数据 ...
- 四则运算-ppt演示
- Gradle下载类库源码
https://blog.csdn.net/xiaoxing598/article/details/68958383 备选:https://www.cnblogs.com/yoyotl/p/62917 ...
- GS使用HTTPS登录的设置过程
1. Windows 增加角色服务 服务器配置管理器, 添加角色服务 增加角色功能里面有: 证书颁发机构 证书颁发机构 web注册 2. AD CS配置 主要是next操作 独立ca 根证书 等 3. ...
- Angular 序列化和反序列化和遍历
<!DOCTYPE html><html ng-app="myApp"><head lang="en"> <meta ...
- CSS 选择器继承和层叠
CSS选择器及其继承特性.层叠特性1.基本选择器 标记 id class 这个就不再作介绍了 2.复合选择器 交集 交集选择器由两个选择器直接连接构成,其结果是选中二者各自元素范围的交集 其 ...
- Hive三种安装模式
- scipy线性模块liner(linalg)
#liner import numpy as np from scipy import linalg as lg arr=np.array([[1,1],[0,1]]) matr=np.mat('[1 ...