题目大意:给定 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启发式合并的更多相关文章

  1. 洛谷P3224 永无乡 [HNOI2012] 线段树/splay/treap

    正解:线段树合并 解题报告: 传送门! 这题也是有很多解法,eg:splay,treap,... 然而我都不会我会学的QAQ! 反正今天就只讲下线段树合并怎么做QAQ 首先看到这样子的说第k重要的是什 ...

  2. BZOJ2733 [HNOI2012]永无乡(并查集+线段树合并)

    题目大意: 在$n$个带权点上维护两个操作: 1)在点$u,v$间连一条边: 2)询问点$u$所在联通块中权值第$k$小的点的编号,若该联通块中的点的数目小于$k$,则输出$-1$: 传送门 上周的模 ...

  3. 洛谷 [P3224] 永无乡

    Treap 的合并 首先感谢 @Capella 的DeBug 其次,这是由一个 & 号引发的血案 注意对于所有修改操作都要 & Treap的合并, 启发式合并,对于每一个节点都 ins ...

  4. bzoj 2733 永无乡 - 并查集 - 线段树

    永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛. ...

  5. BZOJ 2733 [HNOI2012]永无乡 (权值线段树启发式合并+并查集)

    题意: n<=1e5的图里,在线连边.查询某连通块第k大 思路: 练习线段树合并的好题,因为依然记得上一次启发式合并trie的时候内存爆炸的恐怖,所以这次还是用了动态开点.回收 听说启发式合并s ...

  6. 【BZOJ2733】永无乡(线段树,启发式合并)

    题意:支持合并,求块内K小数 对于 100%的数据 n≤100000,m≤n,q≤300000 思路:对于每一个块建立一棵动态开点的线段树,暴力(启发式?)合并后二分下就行了 merge用函数的方式写 ...

  7. B20J_2733_[HNOI2012]永无乡_权值线段树合并

    B20J_2733_[HNOI2012]永无乡_权值线段树合并 Description:n座岛,编号从1到n,每座岛都有自己的独一无二的重要度,按照重要度可以将这n座岛排名,名次用1到 n来表示.某些 ...

  8. 洛谷P1525 关押罪犯(并查集、二分图判定)

    本人蒟蒻,只能靠题解AC,看到大佬们的解题思路,%%%%%% https://www.luogu.org/problemnew/show/P1525 题目描述 S城现有两座监狱,一共关押着N名罪犯,编 ...

  9. Bzoj1015/洛谷P1197 [JSOI2008]星球大战(并查集)

    题面 Bzoj 洛谷 题解 考虑离线做法,逆序处理,一个一个星球的加入.用并查集维护一下连通性就好了. 具体来说,先将被消灭的星球储存下来,先将没有被消灭的星球用并查集并在一起,这样做可以路径压缩,然 ...

随机推荐

  1. jenkins中配置svn 出现absolute path is not allowed

    代码: 兵马未动,粮草先行 作者: 传说中的汽水枪 如有错误,请留言指正,欢迎一起探讨. 转载请注明出处. 想用jenkins作自动化部署tomcat. svn代码已经checkout到本地目录了(/ ...

  2. linux内核分析第四次实验

    实验步骤: 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用.本次实验中我使用第20号系统调用getpid()函数,用于取得进程识别码. C代码(getpid.c): #include ...

  3. Oracle系列(一): Oracle数据恢复

     Oracle数据恢复 在使用Oracle的时候,突然一部小心update或者delete全部数据后怎么办? select * from table as of timestamp to_timest ...

  4. Glace:generator-jhipster, adding User entity enhancement management

    https://github.com/jhipster/generator-jhipster/issues/2538 jhipster,很好用的开发工具.国外知名度高,国内未普及,国外大公司在用. j ...

  5. Eclipse: Difference between clean, build and publish

    https://stackoverflow.com/questions/5656989/eclipse-difference-between-clean-build-and-publish http: ...

  6. [转载]Memory Limits for Windows and Windows Server Releases

    Memory Limits for Windows and Windows Server Releases This topic describes the memory limits for sup ...

  7. vCenter简单查看多少虚拟机在开机状态和一共多少虚拟机

    vCenter 界面上面不好找 具体的开机 运行数目 但是数据库里面比较好差 登录vCenter的数据库. 查看表主要是 查看正在开机的虚拟机 select * from dbo.VPX_VM WHE ...

  8. []转帖] 浅谈Linux下的五种I/O模型

    浅谈Linux下的五种I/O模型 https://www.cnblogs.com/chy2055/p/5220793.html  一.关于I/O模型的引出 我们都知道,为了OS的安全性等的考虑,进程是 ...

  9. Java和Android的Lru缓存,及其实现原理

    一.概述 Android提供了LRUCache类,可以方便的使用它来实现LRU算法的缓存.Java提供了LinkedHashMap,可以用该类很方便的实现LRU算法,Java的LRULinkedHas ...

  10. rabbitmq使用报错总结

    最近公司重构服务器架构,需要用到rabbitmq,在公司搞了一个下午还是连接不上,后来细看了英文说明,测试连接成功,得出如下报错几点. 我用的安装包:otp_win64_21.3.exe(erlang ...