题目描述

永无乡包含 nnn 座岛,编号从 111 到 nnn ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 nnn 座岛排名,名次用 111 到 nnn 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛到达另一个岛。如果从岛 aaa 出发经过若干座(含 000 座)桥可以 到达岛 bbb ,则称岛 aaa 和岛 bbb 是连通的。

现在有两种操作:

B x y 表示在岛 xxx 与岛 yyy 之间修建一座新桥。

Q x k 表示询问当前与岛 xxx 连通的所有岛中第 kkk 重要的是哪座岛,即所有与岛 xxx 连通的岛中重要度排名第 kkk 小的岛是哪座,请你输出那个岛的编号。

输入输出格式

输入格式:

第一行是用空格隔开的两个正整数 nnn 和 mmm ,分别表示岛的个数以及一开始存在的桥数。

接下来的一行是用空格隔开的 nnn 个数,依次描述从岛 111 到岛 nnn 的重要度排名。随后的 mmm 行每行是用空格隔开的两个正整数 aia_iai​ 和 bib_ibi​ ,表示一开始就存在一座连接岛 aia_iai​ 和岛 bib_ibi​ 的桥。

后面剩下的部分描述操作,该部分的第一行是一个正整数 qqq ,表示一共有 qqq 个操作,接下来的 qqq 行依次描述每个操作,操作的 格式如上所述,以大写字母 QQQ 或 BBB 开始,后面跟两个不超过 nnn 的正整数,字母与数字以及两个数字之间用空格隔开。

输出格式:

对于每个 Q x k 操作都要依次输出一行,其中包含一个整数,表示所询问岛屿的编号。如果该岛屿不存在,则输出 −1-1−1 。

输入输出样例

输入样例#1:

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
输出样例#1:

-1
2
5
1
2

说明

对于 20% 的数据 n≤1000,q≤1000n \leq 1000, q \leq 1000n≤1000,q≤1000

对于 100% 的数据 n≤100000,m≤n,q≤300000n \leq 100000, m \leq n, q \leq 300000 n≤100000,m≤n,q≤300000

提交地址 : Luogu;

      bzoj

用并查集及维护, 无旋Treap直接启发式合并水过

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
#define inf 0x3f3f3f3f
#define maxn 100010 int n, m;
int rt[maxn], tot; struct fhq
{
int ch[];
int val;
int pri;
int siz;
}t[maxn]; int find(int x)
{
return x == rt[x] ? x : rt[x] = find(rt[x]);
} void pushup(int o)
{
t[o].siz = t[t[o].ch[]].siz + t[t[o].ch[]].siz + ;
} void Split(int o, int k, int &x, int &y)
{
if(!o) x = y = ;
else
{
if(t[o].val <= k)
{
x = o;
Split(t[o].ch[], k, t[o].ch[], y);
}
else
{
y = o;
Split(t[o].ch[], k, x, t[o].ch[]);
}
pushup(o);
}
} int Merge(int x, int y)
{
if(!x || !y) return x + y;
if(t[x].pri < t[y].pri)
{
t[x].ch[] = Merge(t[x].ch[], y);
pushup(x);
return x;
}
else
{
t[y].ch[] = Merge(x, t[y].ch[]);
pushup(y);
return y;
} } void insert(int &root, int y)
{
int a, b;
int v = t[y].val;
Split(root, v, a, b);
root =Merge(Merge(a, y), b);
} void DFS(int x, int &y)
{
if(!x) return;
DFS(t[x].ch[], y);
DFS(t[x].ch[], y);
t[x].ch[] = t[x].ch[] = ;
insert(y, x);
} int HeBing(int x, int y)
{
if(t[x].siz > t[y].siz) swap(x, y);
DFS(x, y);
return y;
} int K_th(int o, int k)
{
while()
{
if(k <= t[t[o].ch[]].siz)
{
o = t[o].ch[];
}
else if(k == t[t[o].ch[]].siz + )
{
return o;
}
else
{
k -= t[t[o].ch[]].siz + ;
o = t[o].ch[];
}
}
} int sz[maxn], old[maxn]; int main()
{
srand();
cin >> n >> m;
memset(old, -, sizeof old);
for(register int i = ; i <= n ; i ++)
{
scanf("%d", &t[i].val);
t[i].pri = rand();
t[i].siz = ;
rt[i] = i;
old[t[i].val] = i;
sz[i] = ;
} for(register int i = ; i <= m ; i ++)
{
int a, b, c;
scanf("%d%d", &a, &b);
int fx = find(a), fy = find(b);
if(fx == fy) continue; c = HeBing(rt[a], rt[b]); fx = find(a), fy = find(b); rt[fx] = rt[fy] = c; rt[c] = c;
} int q;
cin >> q;
while(q--)
{
char ch;
int x, y;
int a, b, c;
cin >> ch;
scanf("%d%d", &x, &y);
if(ch == 'Q')
{
int fx = find(x);
printf("%d\n", old[t[K_th(rt[x], y)].val]);
}
else
{
int fx = find(x), fy = find(y);
if(fx == fy) continue;
c = HeBing(rt[x], rt[y]);
fx = find(x), fy = find(y); rt[fx] = rt[fy] = c;
rt[c] = c; }
}
return ; }

zZhBr

HNOI2012 永无乡 无旋Treap的更多相关文章

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

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

  2. 【bzoj2733】永无乡(无旋treap启发式合并 + 并查集)

    传送门 题目分析 起初每个岛都是一个平衡树, 并查集的祖先都是自己.合并两岛时,pri较小的祖先会被作为合并后的祖先, 而两颗平衡树采用启发式合并.查询k值就是基本操作. code #include& ...

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

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

  4. 【bzoj2733】[HNOI2012]永无乡 Treap启发式合并

    题目描述 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达 ...

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

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

  6. [Luogu 3224] HNOI2012 永无乡

    [Luogu 3224] HNOI2012 永无乡 特别水一个平衡树题. 不认真的代价是调试时间指数增长. 我写的 SBT,因为 Treap 的 rand() 实在写够了. 用并查集维护这些点的关系, ...

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

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

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

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

  9. B20J_2733_[HNOI2012]永无乡_权值线段树合并

    B20J_2733_[HNOI2012]永无乡_权值线段树合并 Description:n座岛,编号从1到n,每座岛都有自己的独一无二的重要度,按照重要度可以将这n座岛排名,名次用1到 n来表示.某些 ...

随机推荐

  1. springboot---redis缓存的使用

    1.下载redis安装包,解压到电脑 2.启动redis 3.springboot  application.properties中配置redis缓存 spring.redis.host=127.0. ...

  2. 小程序·云开发的HTTP API调用丨实战

    小程序云开发之httpApi调用. 小程序云开发之httpApi调用(返回"47001处理") 技术栈 采用 nodejs + express 搭建web服务器,采用 axios ...

  3. 装系统 ---------- 了解 UEFI与Legacy、硬盘分区MBR和GPT

    UEFI:全称“统一的可扩展固件接口”(Unified Extensible Firmware Interface),一种详细描述类型接口的标准.这种接口用于操作系统自动从预启动的操作环境,加载到一种 ...

  4. DirectX12 3D 游戏开发与实战第四章内容(下)

    Direct3D的初始化(下) 学习目标 了解Direct3D在3D编程中相对于硬件所扮演的角色 理解组件对象模型COM在Direct3D中的作用 掌握基础的图像学概念,例如2D图像的存储方式,页面翻 ...

  5. Day 2 Bash shell 认识

    1.拍摄虚拟机的快照 2. 什么是Bash shell? 命令解释器,将用户输入的命令,翻译给内核程序,将用户输入的指令翻译给内核 程序,内核处理完成之后将结果返回给bash. 如何打开一个bash窗 ...

  6. 04 (H5*) Vue第四天

    目录: 1:父组件向子组件传值,通过属性绑定的方式. 2:父组件向子组件传方法,通过事件绑定的方式 . 3:通过ref来获取Dom元素 1:父组件向子组件传值,通过属性绑定的方式 1.1:父组件声明数 ...

  7. 跟我学SpringCloud | 第十八篇:微服务 Docker 化之基础环境

    1. 容器化 Docker 的横空出世,给了容器技术带来了质的飞跃,Docker 标准化了服务的基础设施,统一了应用的打包分发,部署以及操作系统相关类库等,解决了测试生产部署时环境差异的问题.对于运维 ...

  8. librosa语音信号处理

    librosa是一个非常强大的python语音信号处理的第三方库,本文参考的是librosa的官方文档,本文主要总结了一些重要,对我来说非常常用的功能.学会librosa后再也不用用python去实现 ...

  9. MySQL之增删改查之

    MySQL之增删改查   前言:以下是MySQL最基本的增删改查语句,很多IT工作者都必须要会的命令,也是IT行业面试最常考的知识点,由于是入门级基础命令,所有所有操作都建立在单表上,未涉及多表操作. ...

  10. JS的运动1(从简单到复杂运动,从单一属性到多属性同时进行的运动过程分析)

    js运动原理 运动基础 在js中,让一个元素动起来的最简单的方式,就是点击按钮,让元素移动.下面是一个简单的案例:(下面几个案例的的html和css都是采用这个为例) <!DOCTYPE htm ...