【bzoj2733】永无乡(无旋treap启发式合并 + 并查集)
题目分析
起初每个岛都是一个平衡树, 并查集的祖先都是自己。合并两岛时,pri较小的祖先会被作为合并后的祖先, 而两颗平衡树采用启发式合并。查询k值就是基本操作。
code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std; const int N = 1e5 + ;
int n, m;
#define SZ(x) (x?x->sze:0)
struct node{
node *lc, *rc;
int pri, sze, val, num;
inline node* upt(){
sze = SZ(lc) + SZ(rc) + ;
return this;
}
}pool[N], *tail = pool, *nod[N];
int fa[N]; inline int Rand(){
static int RAND_VAL = ;
return RAND_VAL += RAND_VAL << | ;
} inline node* newNode(int v, int k){
node *x = ++tail;
x->sze = , x->val = v, x->pri = Rand(), x->num = k;
return x;
} inline node* Merge2(node *u, node *v){
if(!u) return v;
if(!v) return u;
if(u->pri < v->pri){
u->rc = Merge2(u->rc, v);
return u->upt();
}
else{
v->lc = Merge2(u, v->lc);
return v->upt();
}
} inline int getAnc(int a){
return fa[a] == a ? a : (fa[a] = getAnc(fa[a]));
} inline void Split_v(node *u, int v, node *&x, node *&y){
if(!u){
x = y = NULL;
return;
}
if(u->val <= v){
Split_v(u->rc, v, x, y);
u->rc = NULL, u->upt();
x = Merge2(u, x);
}
else{
Split_v(u->lc, v, x, y);
u->lc = NULL, u->upt();
y = Merge2(y, u);
}
} inline void Split_k(node *u, int k, node *&x, node *&y){
if(!u){
x = y = NULL;
return;
}
if(SZ(u->lc) < k){
Split_k(u->rc, k - SZ(u->lc) - , x, y);
u->rc = NULL, u->upt();
x = Merge2(u, x);
}
else{
Split_k(u->lc, k, x, y);
u->lc = NULL, u->upt();
y = Merge2(y, u);
}
} inline node* Merge(node *u, node *v){
if(!u) return v;
if(!v) return u;
node *L, *R;
if(u->pri > v->pri) swap(u, v);
Split_v(v, u->val, L, R);
u->lc = Merge(u->lc, L);
u->rc = Merge(u->rc, R);
return u->upt();
} inline int read(){
int i = , f = ; char ch = getchar();
for(; (ch < '' || ch > '') && ch != '-'; ch = getchar());
if(ch == '-') f = -, ch = getchar();
for(; ch >= '' && ch <= ''; ch = getchar())
i = (i << ) + (i << ) + (ch - '');
return i * f;
} inline void wr(int x){
if(x < ) putchar('-'), x = -x;
if(x > ) wr(x / );
putchar(x % + '');
} int main(){
n = read(), m = read();
for(int i = ; i <= n; i++) fa[i] = i;
for(int i = ; i <= n; i++) nod[i] = newNode(read(), i);
for(int i = ; i <= m; i++){
int a = read(), b = read();
int fu = getAnc(a), fv = getAnc(b);
if(fu != fv){
if(nod[fu]->pri < nod[fv]->pri) fa[fv] = fu, nod[fu] = Merge(nod[fu], nod[fv]);
else fa[fu] = fv, nod[fv] = Merge(nod[fu], nod[fv]);
}
}
// for(int i = 1; i <= n; i++) cout<<i<<":"<<nod[i]->sze<<endl;
int Q = read();
for(int i = ; i <= Q; i++){
char opt[]; scanf("%s", opt);
if(opt[] == 'Q'){
node *L, *R, *p, *q;
int x = read(), k = read(), fx = getAnc(x);
// cout<<x<<" "<<k<<" "<<fx<<" "<<endl;
Split_k(nod[fx], k - , L, R);
Split_k(R, , p, q);
if(p) wr(p->num);
else wr(-);
putchar('\n');
nod[fx] = Merge2(L, Merge2(p, q));
}
else{
int a = read(), b = read();
int fu = getAnc(a), fv = getAnc(b);
if(fu != fv){
if(nod[fu]->pri < nod[fv]->pri) fa[fv] = fu, nod[fu] = Merge(nod[fu], nod[fv]);
else fa[fu] = fv, nod[fv] = Merge(nod[fu], nod[fv]);
}
}
}
return ;
}
【bzoj2733】永无乡(无旋treap启发式合并 + 并查集)的更多相关文章
- BZOJ 2733: [HNOI2012]永无乡(treap + 启发式合并 + 并查集)
不难...treap + 启发式合并 + 并查集 搞搞就行了 --------------------------------------------------------------------- ...
- 【BZOJ2733】永无乡[HNOI2012](splay启发式合并or线段树合并)
题目大意:给你一些点,修改是在在两个点之间连一条无向边,查询时求某个点能走到的点中重要度第k大的点.题目中给定的是每个节点的排名,所以实际上是求第k小:题目求的是编号,不是重要度的排名.我一开始差点被 ...
- bzoj2733 永无乡 splay树的启发式合并
https://vjudge.net/problem/HYSBZ-2733 给一些带权点,有些点是互相连通的, 然后给出2种操作,在两点间加一条边,或者询问一个点所在的连通块内的第k小值的编号 并查集 ...
- 【HNOI2012】永无乡(splay,启发式合并)
题解 Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过 ...
- [HNOI2012] 永无乡 解题报告 (splay+启发式合并)
题目链接:https://www.luogu.org/problemnew/show/P3224#sub 题目: 题目大意: 维护多个联通块,没有删除操作,每次询问某一联通块的第k大 解法: 维护联通 ...
- 【洛谷 P3224】 [HNOI2012]永无乡(Splay,启发式合并)
题目链接 启发式合并就是暴力合并把小的合并到大的里,一个一个插进去. 并查集维护连通性,同时保证并查集的根就是所在Splay的根,这样能省去很多操作. #include <cstdio> ...
- BZOJ 2733 [HNOI2012]永无乡 (权值线段树启发式合并+并查集)
题意: n<=1e5的图里,在线连边.查询某连通块第k大 思路: 练习线段树合并的好题,因为依然记得上一次启发式合并trie的时候内存爆炸的恐怖,所以这次还是用了动态开点.回收 听说启发式合并s ...
- 【20181026T2】**图【最小瓶颈路+非旋Treap+启发式合并】
题面 [错解] 最大最小?最小生成树嘛 蛤?还要求和? 点分治? 不可做啊 写了个MST+暴力LCA,30pts,140多行 事后发现30分是给dijkstra的 woc [正解] 树上计数问题:①并 ...
- BZOJ 3545: [ONTAK2010]Peaks( BST + 启发式合并 + 并查集 )
这道题很好想, 离线, 按询问的x排序从小到大, 然后用并查集维护连通性, 用平衡树维护连通块的山的权值, 合并就用启发式合并.时间复杂度的话, 排序是O(mlogm + qlogq), 启发式合并是 ...
随机推荐
- Docker---(8)Docker启动Redis后访问不了
原文:Docker---(8)Docker启动Redis后访问不了 版权声明:欢迎转载,请标明出处,如有问题,欢迎指正!谢谢!微信:w1186355422 https://blog.csdn.net/ ...
- HDU1969 Pie(二分搜索)
题目大意是要办生日Party,有n个馅饼,有f个朋友.接下来是n个馅饼的半径.然后是分馅饼了, 注意咯自己也要,大家都要一样大,形状没什么要求,但都要是一整块的那种,也就是说不能从两个饼中 各割一小块 ...
- 配置PL/SQL Developer连接server数据库
配置PL/SQL Developer连接server数据库 远程应用server上安装client客户端软件,可在oracle官网上下载. 举例: 环境 应用server操作系统 WIN 7 本地地址 ...
- 添加asp.net mvc到现有的asp.net web form 应用程序
前言 asp.net mvc的前一版本为asp.net web Form(Asp.net mvc之前称为asp.net),其第一个版本与2002年年初发布.asp.net web form 属于.ne ...
- node event中 on emit off 的封装
事件绑定一个事件名称对应多个事件函数 应此它们的关系是一对多的关系 数据类型采用对象的形式 key:val 因为函数有多个 所以val选用数组 事件仓库 eventList = { key:val, ...
- 洛谷—— P1091 合唱队形
https://www.luogu.org/problem/show?pid=1091#sub || http://codevs.cn/problem/1058/ 题目描述 N位同学站成一排,音乐 ...
- 7.2 基础知识ArrayMap
1.android源码中维护有键值对,通过键可以找到值 Java中Object是所有类的父类,对于键值对的保存如果使用个ObjectArray数组,比如N个位置存放键,N+1的位置就存放值,那么如果键 ...
- [Nuxt] Setup a "Hello World" Server-Rendered Vue.js Application with the Vue-CLI and Nuxt
Install: npm install -g vue-cli Init project: vue init nuxt/starter . Run: npm run dev Create a inde ...
- Ubuntu设置IP(VMware9.03)
说明:在VMware上新安装Ubuntu11.04(64位) vi编辑器特难用,输入老出错,费了老大劲才把IP改好,IP改完之后最好立马重装一个编辑器vim. 设置静态IP: # vi /etc/ne ...
- 调试 之gdb thread命令 与 ltrace/strace
我们可以通过 1) gdb prog_name -> r 用在逐步调试自己的程序时 2) gdb -> attach process_id 正 ...