【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), 启发式合并是 ...
随机推荐
- [Angular] Using the Argon 2 Hashing Function In Our Sign Up Backend Service
Which hash algorithom to choose for new application: https://www.owasp.org/index.php/Password_Storag ...
- UVA 11437 - Triangle Fun 向量几何
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
- 在react底下安装环境
1.在react底下安装环境 Image.png Image.png 2.新建一个文件夹 Image.png 3.配置入口文件redux:staticRoot+'/redux/app' Image.p ...
- UVA 11461 - Square Numbers 数学水题
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
- 被误解的MVC和被神化的MVVM
MVC 的历史 MVC,全称是 Model View Controller,是模型 (model)-视图 (view)-控制器 (controller) 的缩写.它表示的是一种常见的客户端软件开发框架 ...
- jquery如何实现点击标题收缩下面的内容
jquery如何实现点击标题收缩下面的内容 一.总结 一句话总结:怎么做复杂前端任务,先把样式(最简单)做出来,然后在写js. 1.如何取jquery集合中的某个索引号的元素? 不是get(),是eq ...
- wordpress-nas
- 机器学习01-kNN邻近算法
k-近邻算法 概述:k-近邻算法採用測量不同特征值之间的距离方法进行分类 长处:精度高.对于异常值不敏感.无数据输入假定 缺点:计算复杂度高,空间复杂度高,而且它没有办法各处基础数据的一些内部信息数据 ...
- 特征点提取之Harris角点提取法
1. 特征点提取的意义 2.角点 3. Harris角点检測的基本原理 4.Harris角点检測算法的步骤 5.Harris角点提取算法设计 <span style="font-siz ...
- 【基础练习】【线性DP】codevs3641 上帝选人题解
这道题目的数据最后一个有问题,特殊处理了 上题目 题目描写叙述 Description 世界上的人都有智商IQ和情商EQ.我们用两个数字来表示人的智商和情商,数字大就代表其对应智商或情商高. 如今你面 ...