题目描述

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

现在有两种操作:

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

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

输入输出格式

输入格式:

输入文件第一行是用空格隔开的两个正整数 n 和 m,分别 表示岛的个数以及一开始存在的桥数。接下来的一行是用空格隔开的 n 个数,依次描述从岛 1 到岛 n 的重要度排名。随后的 m 行每行是用空格隔开的两个正整数 ai 和 bi,表示一开始就存 在一座连接岛 ai 和岛 bi 的桥。后面剩下的部分描述操作,该部分的第一行是一个正整数 q, 表示一共有 q 个操作,接下来的 q 行依次描述每个操作,操作的格式如上所述,以大写字母 Q 或B 开始,后面跟两个不超过 n 的正整数,字母与数字以及两个数字之间用空格隔开。 对于 20%的数据 n<=1000,q<=1000 对于 100%的数据 n<=100000,m<=n,q<=300000

输出格式:

对于每个 Q x k 操作都要依次输出一行,其中包含一个整数,表 示所询问岛屿的编号。如果该岛屿不存在,则输出-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
题解:
splay+并查集
并查集判断两点是否联通,每个节点对应一个平衡树
splay用启发式合并,通过线段树思想和调整顺序可以做到不用旋转
 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=,MAXM=;
int tot2,tot1,s[MAXN],pre[MAXM],ch[MAXM][],key[MAXM];
int size[MAXM],root[MAXN],n,m,set[MAXN],a[MAXN],sz,id[MAXN];
void NewNode(int &x,int fa,int k)
{
if (tot2) x=s[tot2--];
else x=++tot1;
key[x]=k;
size[x]=;
pre[x]=fa;
ch[x][]=ch[x][]=;
}
int find(int x)
{
if (set[x]!=x) set[x]=find(set[x]);
return set[x];
}
void pushup(int x)
{
int lson=ch[x][],rson=ch[x][];
size[x]=size[lson]+size[rson];
}
void insert(int &x,int l,int r,int d)
{
x=++sz;
if (l==r)
{
size[x]=;
return;
}
int mid=(l+r)>>;
if(d<=mid) insert(ch[x][],l,mid,d);
else insert(ch[x][],mid+,r,d);
pushup(x);
}
int merge(int x,int y)
{
if (!x) return y;
if (!y) return x;
ch[x][]=merge(ch[x][],ch[y][]);
ch[x][]=merge(ch[x][],ch[y][]);
pushup(x);
return x;
}
int query(int x,int l,int r,int k)
{
if(l==r) return l;
int mid=(l+r)>>;
if(size[ch[x][]]>=k) return query(ch[x][],l,mid,k);
else return query(ch[x][],mid+,r,k-size[ch[x][]]);
}
void erase(int r)
{
if (!r) return ;
s[++tot2]=r;
erase(ch[r][]);
erase(ch[r][]);
}
void bridge_union(int x,int y)
{
int l=find(x),r=find(y);
if (l!=r)
{
if (size[root[l]]<size[root[r]]) swap(l,r);
set[r]=l;size[root[l]]+=size[root[r]];
merge(root[l],root[r]);
erase(root[r]);
}
}
char get_op()
{
char ch=getchar();
while (ch!='B'&&ch!='Q') ch=getchar();
return ch;
}
int main()
{int i,j,x,y,q,opt;
cin>>n>>m;
for (i=;i<=n;i++)
{
scanf("%d",&a[i]);
id[a[i]]=i;
set[i]=i;
}
for (i=;i<=n;i++)
insert(root[i],,n,a[i]);
for (i=;i<=m;i++)
{
scanf("%d%d",&x,&y);
bridge_union(x,y);
}
cin>>q;
for (i=;i<=q;i++)
{
opt=get_op();
scanf("%d%d",&x,&y);
if (opt=='Q')
{
int l=find(x);
if (size[root[l]]<y) printf("-1\n");
else
printf("%d\n",id[query(root[l],,n,y)]);
}
else
{
bridge_union(x,y);
}
}
}

[HNOI2012]永无乡的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. 线段树合并+并查集 || BZOJ 2733: [HNOI2012]永无乡 || Luogu P3224 [HNOI2012]永无乡

    题面:P3224 [HNOI2012]永无乡 题解: 随便写写 代码: #include<cstdio> #include<cstring> #include<iostr ...

  7. bzoj2733: [HNOI2012]永无乡 启发式合并

    地址:http://www.lydsy.com/JudgeOnline/problem.php?id=2733 题目: 2733: [HNOI2012]永无乡 Time Limit: 10 Sec   ...

  8. [HNOI2012]永无乡 线段树合并

    [HNOI2012]永无乡 LG传送门 线段树合并练手题,写这篇博客只是为了给我的这篇文章找个板子题. 并查集维护连通性,对于不在同一个连通块内的合并操作每次直接合并两颗线段树,复杂度\(O(n \l ...

  9. bzoj2733 / P3224 [HNOI2012]永无乡(并查集+线段树合并)

    [HNOI2012]永无乡 每个联通块的点集用动态开点线段树维护 并查集维护图 合并时把线段树也合并就好了. #include<iostream> #include<cstdio&g ...

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

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

随机推荐

  1. 2018上C语言程序设计(高级)作业- 初步计划

    C语言程序设计(高级)36学时,每周4学时,共9周.主要学习指针.结构和文件三部分内容.整个课程作业计划如下: PTA和博客的使用指南 若第一次使用PTA和博客,请务必先把PTA的使用简介和教师如何在 ...

  2. C/C++生成随机数

    一.rand和srand   在C++11标准出来之前,C/C++都依赖于stdlib.h头文件的rand或者srand来生成随机数.   其不是真正的随机数,是一个伪随机数,是根据一个数(我们可以称 ...

  3. memmove 和 memcpy的区别以及处理内存重叠问题

    区别: memcpy和memmove()都是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,原型分别如下: void *memcpy(void *dst, const v ...

  4. iOS Storyboard unwind segues使用小结

    使用storyboard开发的时候,经常会在一个scene上添加一个button,再拖拽这个button到某个想要关联的页面,最后选择push的方式跳转.这样scene_A和scene_B就有了一个& ...

  5. android 自定义ScrollView实现背景图片伸缩(阻尼效果)

    android 自定义ScrollView实现强调内容背景图片伸缩(仿多米,qq空间背景的刷新) 看到一篇文章,自己更改了一下bug: 原文地址:http://www.aiuxian.com/arti ...

  6. 【iOS】swift-文字宽度的计算

    如图所示,需要sectionView的标题宽度可以动态变化 举例说明: 只需在tableView的代理方法 func tableView(tableView: UITableView, viewFor ...

  7. JAVA_SE基础——67.System类

    System类对大家都不陌生吧! 以前经常需要打印结果时使用的都是"System.out.println()"语句,这句代码中就使用了System类.System类定义了一些与系统 ...

  8. 使用IDEA快速插入数据库数据的方法

    如上图所示:数据库创建表主键使用了自增列自增因此忽略,只有后两列非主键得数据,在数据较多得时候使用IDEA快捷键Ctrl+R键,快速查找替换.

  9. 深入浅出Lua虚拟机

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 作者:郑小辉 | 腾讯 游戏客户端开发高级工程师 写在前面:本文所有的文字都是我手工一个一个敲的,以及本文后面分享的Demo代码都是我一行一 ...

  10. oracle批量插入优化方案

    今天听DBA说如果从一个表批量查询出一批数据之后批量插入另外一张表的优化方案: 1)不写归档日志: 2)采用独占 关于insert /*+ append */我们需要注意以下三点: a.非归档模式下, ...