题意:

n<=1e5的图里,在线连边、查询某连通块第k大

思路:

练习线段树合并的好题,因为依然记得上一次启发式合并trie的时候内存爆炸的恐怖,所以这次还是用了动态开点、回收

听说启发式合并splay更快QAQ,学会了试试

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
#include<functional> #define fst first
#define sc second
#define pb push_back
#define mp make_pair
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1
#define lowbit(x) ((x)&(-x)) using namespace std; typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL; const db eps = 1e-;
const int mod = 1e9+;
const int maxn = 1e5+;
const int maxm = 6e6+;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0); int n,m;
int q;
int ls[maxn*],rs[maxn*],dat[maxn*];
int root[maxn];
int a[maxn],id[maxn]; int f[maxn];
int find(int x){
return f[x]==x?x:f[x]=find(f[x]);
} int tot;
queue<int>pool;
int New(){
if(!pool.empty()){
int x = pool.front();
pool.pop();
return x;
}
++tot;
return tot;
}
void del(int x){
if(!x)return;
pool.push(x);
return;
}
int build(int l, int r, int x){
int mid = (l+r)>>;
int p = New();
dat[p]=;
if(l==r)return p;
if(x<=mid)ls[p]=build(l,mid,x);
else rs[p]=build(mid+,r,x);
return p;
}
int merge(int p, int q){// leave p
if(!p)return q;
if(!q)return p;
ls[p]=merge(ls[p],ls[q]);
rs[p]=merge(rs[p],rs[q]);
dat[p]+=dat[q];
ls[q]=rs[q]=dat[q]=;
del(q);
return p;
}
int query(int x, int l, int r, int k){
int mid = (l+r)>>;
if(l==r)return l;
if(dat[ls[x]]>=k){
return query(ls[x],l,mid,k);
}
else{
return query(rs[x],mid+,r,k-dat[ls[x]]);
}
}
int main() {
scanf("%d %d" ,&n, &m);
for(int i = ; i <= n; i++){
f[i]=i;
scanf("%d", &a[i]);
id[a[i]]=i;
root[i]=build(,n,a[i]);
}
/*for(int i = 1; i <= n; i++){
printf("-- %d root::%d\n",i,root[i]);
}
for(int i = 1; i <= tot; i++){
//printf("%d ==== %d %d %d\n",i,ls[i],rs[i],dat[i]);
}*/
for(int i = ; i <= m; i++){
int x,y;
scanf("%d %d" ,&x, &y);
int t1 = find(x);
int t2 = find(y);
if(t1!=t2){
root[t1]=merge(root[t1],root[t2]);
f[t2]=t1;
}
}
scanf("%d", &q);
while(q--){
char op[];
int x,y;
scanf("%s %d %d", op,&x,&y);
if(op[]=='Q'){
int t = find(x);
if(dat[root[t]]<y){printf("-1\n");continue;}
else printf("%d\n",id[query(root[t],,n,y)]);
}
else{
int t1 = find(x);
int t2 = find(y);
if(t1!=t2){
root[t1]=merge(root[t1],root[t2]);
f[t2]=t1;
}
}
}
return ;
}
/*
5 1
4 3 2 5 1
1 2
7
Q 3 2
Q 2 1
B 2 3
B 1 5
Q 2 1
Q 2 4
Q 2 3
*/

BZOJ 2733 [HNOI2012]永无乡 (权值线段树启发式合并+并查集)的更多相关文章

  1. BZOJ2733/LG3324 「HNOI2014」永无乡 权值线段树合并

    问题描述 BZOJ2733 LG3224 题解 对于每个结点建立一棵权值线段树. 查询操作就去查询第 \(k\) 大,合并操作就合并两颗权值线段树. 并查集维护连通性. 同时 STO hkk,zcr, ...

  2. bzoj 2733: [HNOI2012]永无乡 -- 线段树

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MB Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自 ...

  3. Bzoj 2733: [HNOI2012]永无乡(线段树+启发式合并)

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec Memory Limit: 128 MB Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己 ...

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

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

  5. BZOJ 2733: [HNOI2012]永无乡 启发式合并treap

    2733: [HNOI2012]永无乡 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  6. bzoj 2733: [HNOI2012]永无乡 离线+主席树

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1167  Solved: 607[Submit][Status ...

  7. BZOJ 2733: [HNOI2012]永无乡(treap + 启发式合并 + 并查集)

    不难...treap + 启发式合并 + 并查集 搞搞就行了 --------------------------------------------------------------------- ...

  8. Bzoj 2733: [HNOI2012]永无乡 数组Splay+启发式合并

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

  9. bzoj 2733: [HNOI2012]永无乡【并查集+权值线段树】

    bzoj上数组开大会T-- 本来想用set瞎搞的,想了想发现不行 总之就是并查集,每个点开一个动态开点的权值线段树,然后合并的时候把值并在根上,询问的时候找出在根的线段树里找出k小值,看看这个值属于哪 ...

随机推荐

  1. 微信小程序开发笔记(二)

    一.前言 继承上一篇所说的,有了对微信小程序的基础概念后,这边将会示范动手做一个小程序,在动手的过程中我们可以更快的熟悉小程序里面的架构和开发流程. 二.小程序的设计 这次要做的是一个猜数字的程序,程 ...

  2. linux常用命令,最基础

    rmdir keda1/ 6 touch test.java 创建空文件 7 拷贝文件 cp 源文件 目标文件 cp test.java test1.java 8 删除文件rm -r 递归删除 -rf ...

  3. 「newbee-mall新蜂商城开源啦」1000 Star Get !仓库Star数破千!记录一下

    新蜂商城已经开源了 3 个多月左右的时间,在 2019 年的年末,仓库的 Star 数量冲破了 1000,整理本篇文章的时间是 2020 年 1 月 12 日,目前的 Star 数量是 1180 左右 ...

  4. UGUI源码之EventSystem

    今天研究下UGUI的源码,先从EventSystem入手.EventSystem是用来处理点击.键盘输入以及触摸等事件的. 1.BaseInputModule EventSystem开头声明了两个变量 ...

  5. TensorFlow——常见张量操作的API函数

    1.张量 张量可以说是TensorFlow的标志,因为整个框架的名称TensorFlow就是张量流的意思,全面的认识一下张量.在TensorFlow程序使用tensor数据结构来代表所有的数据,在计算 ...

  6. MADP(移动应用开发平台)推动企业数字化转型

    移动互联网时代,企业对于移动应用程序的需求呈现爆炸式增长,移动解决方案供应商一直致力于寻找解决方案帮助企业完成这些移动集成需求,MADP(移动应用开发平台)因此产生,MADP允许提供一种解决方案,可以 ...

  7. Graph Transformer Networks 论文分享

    论文地址:https://arxiv.org/abs/1911.06455 实现代码地址:https://github.com/ seongjunyun/Graph_Transformer_Netwo ...

  8. 想玩转JAVA高并发,这些概念你必须懂!

    我们在找工作时,经常在招聘信息上看到有这么一条:有构建大型互联网服务及高并发等经验,你第一时间想到的是媒体常说的双十一吗?带着问题,我们一起思考技术…. 高并发高并发 它是互联网分布式系统架构设计中必 ...

  9. 2020寒假学习01 Scala 编程初级实践

    1. 计算级数请用脚本的方式编程计算并输出下列级数的前 n 项之和 Sn,直到 Sn 刚好大于或等于 q为止,其中 q 为大于 0 的整数,其值通过键盘输入. Sn = 2/1+3/2+4/3+... ...

  10. 《大道至简》第一章Java伪代码读后感

    /*写程序,实际是一种方法论.从另外一个角度帮我们看待世界,看清事物的本质. 早在两千年前的寓言中,愚公和智叟的问答中就已体现整个工程的实现程序.*/ public class 移山{ string ...