【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), 启发式合并是 ...
随机推荐
- 00103_死锁、Lock接口、等待唤醒机制
1.死锁 (1)同步锁使用的弊端:当线程任务中出现了多个同步(多个锁)时,如果同步中嵌套了其他的同步.这时容易引发一种现象:程序出现无限等待,这种现象我们称为死锁.这种情况能避免就避免掉: synch ...
- 一个Java8模型的batch队列
有点小问题,cpu过高,但是思路不错: http://www.tuicool.com/articles/URz2i2q
- 洛谷—— P1434 滑雪
https://www.luogu.org/problem/show?pid=1434#sub 题目描述 Michael喜欢滑雪.这并不奇怪,因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜 ...
- C# exe文件 添加到windows 服务
我们运行.net的发布工具installutil.exe来添加到windows服务里面(该工具默认在C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727目录下) ...
- Rick's RoTs -- Rules of Thumb for MySQL--转载
原文地址:http://mysql.rjweb.org/doc.php/ricksrots Brought to you by Rick James Here are 160+ tips, trick ...
- jmeter--函数助手对话框之参数详解
详解JMeter函数和变量 测试人员可以在JMeter的选项菜单中找到函数助手对话框("Function Helper"对话框),如图11-1所示. 图11-1 函数助手(Func ...
- mysql的入门基础操作
1.数据库的简单介绍 1.1 什么是数据库,就是一个文件系统,使用标准sql对数据库进行操作 1.2 常见的数据库 oracle 是oracle公司的数据库,是一个收费的大型的数据库 DB2,是IB ...
- cocos 关于文件名称的各种坑 各种斜杠坑
cocos 全部文件路径 的斜杠 必须 用 / 而不能够用 \ 不然编译到安卓各种坑 相对路径 第一个字符不可 带 / /*比如 res/test.png 这样的应该是标准的 /res/test.p ...
- Java反射学习总结一(基础篇)
Class类是Reflection API中核心的类,他位于Java.lang.Class 列出一些常用的方法. - getName() : 获得类的完整名字 - getFields() : 获得类的 ...
- AIR 初步 Javascript学习之cookie操作
//设置cookie的名称,值,过期时间 function setCookie(cookieName,cookieValue,cookieExpire) { v ...