【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), 启发式合并是 ...
随机推荐
- 如何使用VS2008打开VS2010的解决方案
用记事本打开VS2010的SLN文件的修改开头代码: Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Stud ...
- 00091_字符输入流Reader
1.字符输入流Reader (1)字符输入流Reader我们读取拥有中文的文件时,使用的字节流在读取,那么我们读取到的都是一个一个字节: (2)只要把这些字节去查阅对应的编码表,就能够得到与之对应的字 ...
- C语言创建删不掉的目录
上一篇博客写了一个杀不死的进程,如今再写一个删不掉的目录(文件同理),所谓删不掉不是真的删不掉而是删掉后立即又一次创建. 代码例如以下: #include <stdio.h> #inclu ...
- 【BZOJ 4516】生成魔咒
[链接]h在这里写链接 [题意] [Description] 给你n(n<=10^9)个数字,把它们依次,一个一个地添加在空串S的后面. 要求每添加一次之 ...
- hdu 3605 Escape 二分图的多重匹配(匈牙利算法)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3605 Escape Time Limit: 4000/2000 MS (Java/Others) ...
- 三、链路追踪系统 zipkin
一.构建项目 用到的依赖直接看pom.xml的注释吧 <?xml version="1.0" encoding="UTF-8"?> <proj ...
- CTR深度学习
深度学习在 CTR 中应用 一. Wide&&Deep 模型 首先给出Wide && Deep [1] 网络结构: 本质上是线性模型(左边部分, Wide model) ...
- (十二)RabbitMQ消息队列-性能测试
原文:(十二)RabbitMQ消息队列-性能测试 硬件配置 宿主机用的联想3850X6的服务器四颗E7-4850v3的处理器,DDR4内存,两块1.25TB的pcie固态.在宿主机上使用的事esxi5 ...
- 在Scope利用Content sharing Widget来分享内容
在最新的Scope Widget中,有一个新的Content Sharing Widget.我们能够利用这个Widget来分享我们的图片到信息.Facebook,Twitter等渠道.比方,在我们的S ...
- 【2016 Summary】为过往补课、为将来夯实
前言 看了CSDN上非常多"我的2016"年终总结,也就不能免俗地来写一波.按着时间轴捋一捋这过去一年的经过,也算是这元旦假期总一个午后的休闲时光了.(结果没想到的是午饭前開始写的 ...