HNOI2012 永无乡 无旋Treap
题目描述
永无乡包含 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 。
输入输出样例
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
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;
用并查集及维护, 无旋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的更多相关文章
- BZOJ 2733: [HNOI2012]永无乡 启发式合并treap
2733: [HNOI2012]永无乡 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...
- 【bzoj2733】永无乡(无旋treap启发式合并 + 并查集)
传送门 题目分析 起初每个岛都是一个平衡树, 并查集的祖先都是自己.合并两岛时,pri较小的祖先会被作为合并后的祖先, 而两颗平衡树采用启发式合并.查询k值就是基本操作. code #include& ...
- BZOJ 2733: [HNOI2012]永无乡(treap + 启发式合并 + 并查集)
不难...treap + 启发式合并 + 并查集 搞搞就行了 --------------------------------------------------------------------- ...
- 【bzoj2733】[HNOI2012]永无乡 Treap启发式合并
题目描述 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达 ...
- Bzoj 2733: [HNOI2012]永无乡 数组Splay+启发式合并
2733: [HNOI2012]永无乡 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3955 Solved: 2112[Submit][Statu ...
- [Luogu 3224] HNOI2012 永无乡
[Luogu 3224] HNOI2012 永无乡 特别水一个平衡树题. 不认真的代价是调试时间指数增长. 我写的 SBT,因为 Treap 的 rand() 实在写够了. 用并查集维护这些点的关系, ...
- bzoj 2733: [HNOI2012]永无乡 离线+主席树
2733: [HNOI2012]永无乡 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1167 Solved: 607[Submit][Status ...
- BZOJ 2733: [HNOI2012]永无乡 [splay启发式合并]
2733: [HNOI2012]永无乡 题意:加边,询问一个连通块中k小值 终于写了一下splay启发式合并 本题直接splay上一个节点对应图上一个点就可以了 并查集维护连通性 合并的时候,把siz ...
- B20J_2733_[HNOI2012]永无乡_权值线段树合并
B20J_2733_[HNOI2012]永无乡_权值线段树合并 Description:n座岛,编号从1到n,每座岛都有自己的独一无二的重要度,按照重要度可以将这n座岛排名,名次用1到 n来表示.某些 ...
随机推荐
- AirFlow常用命令
airflow常用命令如下所示: airflow test dag_id task_id execution_date 测试task 示例: airflow test example_hello_wo ...
- CCPC桂林
在得知我们队伍前往桂林参加CPPC区域赛后,我是非常激动的,因为我们网络赛并没有得到名额,如果不是新都赠予我们名额,我们都没有出去打比赛的机会,同时,我们也不想浪费这个名额,我们也想打出成绩来,于是我 ...
- CSS——样式表的引入
1.内部样式表 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <t ...
- 字节输出流OutputStream
1.OutputStream是输出字节流的超类. import java.io.File; import java.io.FileOutputStream; import java.io.IOExce ...
- 实战限流(guava的RateLimiter)
关于限流 常用的限流算法有漏桶算法和令牌桶算法,guava的RateLimiter使用的是令牌桶算法,也就是以固定的频率向桶中放入令牌,例如一秒钟10枚令牌,实际业务在每次响应请求之前都从桶中获取令牌 ...
- C# HTTP网络常用方法封装
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Regi ...
- HTML定位——绝对定位和相对定位、固定定位
1.绝对定位 绝对定位指的是通过规定HTML元素在水平和垂直方向上的位置来固定元素,基于绝对定位的元素不会占据空间. 绝对定位的位置声明是相对于已定位的并且包含关系最近的祖先元素.如果当前需要被定为的 ...
- 谁是狸猫谁是太子?--戏说java构造器
故事背景 <狸猫换太子>在我国民间文学中很出名,故事剧情大致如下:北宋第三位皇帝宋真宗赵恒年长无子,他的两个妃子刘妃与李妃同时怀了身孕.真宗召见二人,各赐信物,并声明哪个生了儿子就立谁为皇 ...
- 怎样用手机把视频变成GIF表情包?原来那么简单,网友:看完涨知识了
现如今表情包几乎成了,我们手机聊天的必需品了.不过相比于普通表情包,大家更喜欢用GIF表情包,因为动图表情包不仅更加搞笑,而且能更形象的表达我们的情绪.比较有想法的朋友甚至想自己制作GIF表情包,但是 ...
- 关于CDH集群spark的三种安装方式简述
一.spark的命令行模式 1.第一种进入方式:执行 pyspark进入,执行exit()退出 注意报错信息:java.lang.IllegalArgumentException: Required ...