题意:给定一个带点权的无向图,有两种操作:

  1、将两个连通分量合并。

  2、查询某个连通分量里的第K大点。

题解:

用并查集维护连通关系,一开始建立n棵splay树,然后不断合并,查询。

处理技巧:

  1、每个顶点u所在的Splay就是T[find(u)]。

  2、每个顶点在树中对应的节点编号就是该顶点的编号。

 #include <cstdio>
#include <iostream>
#define maxn 100110
using namespace std; int key[maxn], pre[maxn], son[maxn][], siz[maxn], ntot;
struct Splay {
int root;
Splay():root(){}
void update( int nd ) {
siz[nd] = siz[son[nd][]] + siz[son[nd][]] + ;
}
void rotate( int nd, int d ) {
int p = pre[nd];
int s = son[nd][!d];
int ss = son[s][d]; son[nd][!d] = ss;
son[s][d] = nd;
if( p ) son[p][ nd==son[p][] ] = s;
else root = s; pre[nd] = s;
pre[s] = p;
if( ss ) pre[ss] = nd; update( nd );
update( s );
}
void splay( int nd, int top= ) {
while( pre[nd]!=top ) {
int p = pre[nd];
int nl = nd==son[p][];
if( pre[p]==top ) {
rotate( p, nl );
} else {
int pp = pre[p];
int pl = p==son[pp][];
if( nl==pl ) {
rotate( pp, pl );
rotate( p, nl );
} else {
rotate( p, nl );
rotate( pp, pl );
}
}
}
}
int initnode( int nd, int k, int p ) {
key[nd] = k;
pre[nd] = p;
son[nd][] = son[nd][] = ;
siz[nd] = ;
return nd;
}
void insert( int k, int nnd ) {
if( !root ) {
root = initnode(nnd,k,);
return;
}
int nd = root;
while( son[nd][ k>key[nd] ] )
nd = son[nd][ k>key[nd] ];
son[nd][ k>key[nd] ] = initnode(nnd,k,nd);
update( nd );
splay( nd );
}
int nth( int n ) {
int nd = root;
while( ) {
int ls = siz[son[nd][]];
if( n<=ls ) {
nd = son[nd][];
} else if( n>=ls+ ) {
nd = son[nd][];
n -= ls+;
} else {
break;
}
}
splay(nd);
return nd;
}
inline int size() { return siz[root]; }
static void join( Splay &T , int snd ) {
if( !snd ) return;
join( T, son[snd][] );
join( T, son[snd][] );
T.insert( key[snd], snd );
}
}; int n, m, q;
int fa[maxn];
Splay T[maxn]; int find( int a ) {
return a==fa[a] ? a : fa[a]=find(fa[a]);
} void join( int a, int b ) {
if( find(a)==find(b) ) return;
if( T[find(a)].size() > T[find(b)].size() ) swap(a,b);
Splay::join( T[find(b)], T[find(a)].root );
fa[find(a)] = find(b);
} int main() {
scanf( "%d%d", &n, &m );
for( int i=,w; i<=n; i++ ) {
scanf( "%d", &w );
fa[i] = i;
T[i].insert( w, i );
}
for( int i=,u,v; i<=m; i++ ) {
scanf( "%d%d", &u, &v );
join(u,v);
}
scanf( "%d", &q );
while( q-- ) {
char ch[];
int a, b;
scanf( "%s%d%d", ch, &a, &b );
if( ch[]=='B' ) {
join(a,b);
} else {
if( !(<=b&&b<=T[find(a)].size()) ) printf( "-1\n" );
else printf( "%d\n", T[find(a)].nth(b) );
}
}
}

bzoj 2733 Splay 启发式合并,名次树的更多相关文章

  1. bzoj2733: [HNOI2012]永无乡(splay+启发式合并/线段树合并)

    这题之前写过线段树合并,今天复习Splay的时候想起这题,打算写一次Splay+启发式合并. 好爽!!! 写了长长的代码(其实也不长),只凭着下午的一点记忆(没背板子...),调了好久好久,过了样例, ...

  2. BZOJ 2733 & splay的合并

    题意: 带权联通块,添边与查询联通块中第k大. SOL: splay合并+并查集. 我以为splay可以用奇技淫巧来简单合并...调了一下午终于幡然醒悟...于是就只好一个一个慢慢插...什么启发式合 ...

  3. bzoj 2733 平衡树启发式合并

    首先对于一个连通块中,询问我们可以直接用平衡树来求出排名,那么我们可以用并查集来维护各个块中的连通情况,对于合并两个平衡树,我们可以暴力的将size小的平衡树中的所有节点删掉,然后加入大的平衡树中,因 ...

  4. BZOJ 2733: [HNOI2012]永无乡 [splay启发式合并]

    2733: [HNOI2012]永无乡 题意:加边,询问一个连通块中k小值 终于写了一下splay启发式合并 本题直接splay上一个节点对应图上一个点就可以了 并查集维护连通性 合并的时候,把siz ...

  5. BZOJ 2733 [HNOI2012]永无乡 - 启发式合并主席树

    Description 1: 查询一个集合内的K大值 2: 合并两个集合 Solution 启发式合并主席树板子 Code #include<cstdio> #include<cst ...

  6. 【BZOJ2733】永无乡[HNOI2012](splay启发式合并or线段树合并)

    题目大意:给你一些点,修改是在在两个点之间连一条无向边,查询时求某个点能走到的点中重要度第k大的点.题目中给定的是每个节点的排名,所以实际上是求第k小:题目求的是编号,不是重要度的排名.我一开始差点被 ...

  7. bzoj 3674: 可持久化并查集加强版 (启发式合并+主席树)

    Description Description:自从zkysb出了可持久化并查集后……hzwer:乱写能AC,暴力踩标程KuribohG:我不路径压缩就过了!ndsf:暴力就可以轻松虐!zky:…… ...

  8. 【BZOJ-2733】永无乡 Splay+启发式合并

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2048  Solved: 1078[Submit][Statu ...

  9. BZOJ2733 永无乡【splay启发式合并】

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

随机推荐

  1. bzoj 1072 状压DP

    我们用w[i][j]来表示,i是一个二进制表示我们选取了s中的某些位,j表示这些位%d为j,w[i][j]则表示这样情况下的方案数,那么我们可以得到转移.w[i|(1<<k)][(j*10 ...

  2. Linux必备工具Tmux

    之前介绍了Linux的Screen命令,今天介绍一个更为强大的终端工具Tmux. Tmux 是一个用于在一个终端窗口中运行多个终端会话的工具.它基本能替代nohup以及screen,甚至比它们更为强大 ...

  3. 记一个多线程使用libevent的问题

    前段时间使用libevent网络库实现了一个游戏服务器引擎,在此记录下其中遇到的一个问题. 我在设计服务器上选择把逻辑和网络分线程,线程之间通信使用队列.但是这样做会有个问题: 当逻辑线程想要主动的发 ...

  4. aws rds

    1.还原快照,注意设置安全组的问题:不然会导致还原后连接不上:

  5. Eloqument 学习

    参考地址:https://d.laravel-china.org/docs/5.5/eloquent#mass-assignment

  6. java版云笔记(七)之事务管理

    事务管理 事务:程序为了保证业务处理的完整性,执行的一条或多条SQL语句. 事务管理:对事务中的SQL语句进行提交或者回滚. 事物管理对于企业应用来说是至关重要的,好使出现异常情况,它也可以保证数据的 ...

  7. jQuery常用事件方法详解

    目录 jQuery事件 ready(fn)|$(function(){}) jQuery.on() jQuery.click jQuery.data() jQuery.submit() jQuery事 ...

  8. leetcode 之Permutation(七)

    首先是next permutation的算法的描述和分析如下: 这题一是要知道思路,编程中注意STL的用法 void nextPermutaion(vector<int> &num ...

  9. 配置Tomcat、maven远程部署调试总结。

    注意:可以搞两个环境,一个本地tomcat 一个服务器上的tomcat ,然后都采用如下配置.这样就可以 在本地调试,调试好后,再发布到服务器端.非常方便.  ==================== ...

  10. open()函数文件操作

    open函数,该函数用于文件处理 操作文件时,一般需要经历如下步骤: (1)打开文件 (2)操作文件 一.打开文件     文件句柄 = open("文件路径","模式& ...