题目描述:

永无乡包含 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。

样例输入:

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

题解:

并查集 + splay(其实所有的平衡树都可以) + 启发式合并

(题外话:这道题我真的是调得生无可恋啊,调了整整三天,提交了两页才调出来

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath> #ifdef WIN32
#define LL "%I64d"
#else
#define LL "%lld"
#endif #ifdef CT
#define debug(...) printf(__VA_ARGS__)
#define setfile()
#else
#define debug(...)
#define filename ""
#define setfile() freopen(filename".in","r",stdin);freopen(filename".out","w",stdout);
#endif #define R register
#define getc() (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?EOF:*S++)
#define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
#define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
#define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
char B[1<<15],*S=B,*T=B;
inline int FastIn()
{
R char ch;R int cnt=0;R bool minus=0;
while (ch=getc(),(ch < '0' || ch > '9') && ch != '-') ;
ch == '-' ?minus=1:cnt=ch-'0';
while (ch=getc(),ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
return minus?-cnt:cnt;
}
#define maxn 100010
int val[maxn], Fa[maxn], ch[maxn][2], fa[maxn], size[maxn];
int Find(R int x){return Fa[x] == x ? x : Fa[x] = Find(Fa[x]);}
inline void update(R int x)
{
R int ls = ch[x][0], rs = ch[x][1];
size[x] = size[ls] + size[rs] + 1;
}
inline void rotate(R int x)
{
R int f = fa[x], gf = fa[f], d = (ch[f][1] == x);
(ch[f][d] = ch[x][d ^ 1]) > 0 ? fa[ch[f][d]] = f : 0;
(fa[x] = gf) > 0 ? ch[gf][ch[gf][1] == f] = x : 0;
fa[ch[x][d ^ 1] = f] = x;
update(f);
}
inline void splay(R int x, R int rt)
{
while (fa[x] != rt)
{
R int f = fa[x], gf = fa[f];
if (gf != rt) rotate((ch[f][1] == x) ^ (ch[gf][1] == f) ? x : f);
rotate(x);
}
update(x);
}
void Insert(R int x, R int f)
{
if (val[x] < val[f])
{
if (ch[f][0])
Insert(x, ch[f][0]);
else
{
ch[f][0] = x; fa[x] = f;
}
}
else
{
if (ch[f][1])
Insert(x, ch[f][1]);
else
{
ch[f][1] = x; fa[x] = f;
}
}
update(f);
}
void merge(R int a, R int b)
{
R int tmp1 = 0, tmp2 = 0;
splay(a, 0);
splay(b, 0);
if (size[a] < size[b])
{
if (ch[a][0]) tmp1 = ch[a][0];
if (ch[a][1]) tmp2 = ch[a][1];
ch[a][0] = 0;
ch[a][1] = 0;
fa[tmp1] = 0;
fa[tmp2] = 0;
if (tmp1) merge(b, tmp1);
if (tmp2) merge(b, tmp2);
Insert(a, b);
}
else
{
if (ch[b][0]) tmp1 = ch[b][0];
if (ch[b][1]) tmp2 = ch[b][1];
ch[b][0] = 0;
ch[b][1] = 0;
fa[tmp1] = 0;
fa[tmp2] = 0;
if (tmp1) merge(a, tmp1);
if (tmp2) merge(a, tmp2);
Insert(b, a);
}
}
int find(R int x, R int k)
{
R int ls = ch[x][0], rs = ch[x][1], lsize = size[ls];
if (lsize + 1 == k) return x;
if (lsize >= k) return find(ls, k);
else return find(rs, k - lsize - 1);
}
int main()
{
R int n = FastIn(), m = FastIn();
for (R int i = 1; i <= n; ++i) val[i] = FastIn(), Fa[i] = i, size[i] = 1;
for (R int i = 1; i <= m; ++i)
{
R int a = FastIn(), b = FastIn();
Fa[Find(a)] = Find(b);
}
for (R int i = 1; i <= n; ++i){
R int f = Find(i);
if (f != i) Insert(i, f);
}
R int q = FastIn();
for (; q; --q)
{
R char opt = getc();
while (opt != 'Q' && opt != 'B') opt = getc();
R int a = FastIn(), b = FastIn();
if (opt == 'B')
{
R int f1 = Find(a), f2 = Find(b);
if (f1!=f2) merge(f1, f2), Fa[f1] = f2;
}
else
{
R int f = Find(a);
splay(f, 0);
if (size[f] < b) puts("-1");
else printf("%d\n",find(f,b) );
}
}
return 0;
}

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

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

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

  2. bzoj2733: [HNOI2012]永无乡(splay)

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3778  Solved: 2020 Description 永 ...

  3. [Bzoj2733][Hnoi2012] 永无乡(BST)(Pb_ds tree)

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

  4. [bzoj2733][HNOI2012]永无乡_权值线段树_线段树合并

    永无乡 bzoj-2733 HNOI-2012 题目大意:题目链接. 注释:略. 想法: 它的查询操作非常友善,就是一个联通块内的$k$小值. 故此我们可以考虑每个联通块建一棵权值线段树. 这样的话每 ...

  5. BZOJ2733 [HNOI2012]永无乡 【线段树合并】

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  6. [BZOJ2733] [HNOI2012] 永无乡 (splay启发式合并)

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

  7. BZOJ2733[HNOI2012]永无乡——线段树合并+并查集+启发式合并

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

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

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

  9. BZOJ2733: [HNOI2012]永无乡(线段树合并)

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

  10. BZOJ2733 [HNOI2012]永无乡

    直接平衡树启发式合并就好了...貌似是个很高端的东西.. 貌似可以证明splay的启发式合并是均摊$O(nlogn)$的...而其他平衡树都不行,所以其他的复杂度都是$O(nlog^2n)的$的 所以 ...

随机推荐

  1. MAC_BOOKPRO苹果电脑系统常用快捷键大全

    Mac 键盘快捷键 我在品多多上拼的Mac终于到货了,安全下车,接下来要熟练使用了! 您可以按下某些组合键来实现通常需要鼠标.触控板或其他输入设备才能完成的操作.   要使用键盘快捷键,请按住一个或多 ...

  2. 全新一台node节点加入到集群中

    目录 前言 对新节点做解析 方法一 hosts 文件解析 方法二 bind 解析 测试 分发密钥对 推送 CA 证书 flanneld 部署 推送flanneld二进制命令 推送flanneld秘钥 ...

  3. arm初识

    一.CPU从指令集角度分类 1.1. CISC  (X86) 1.1. 1. CISC CPU 指complex instruction set computer复杂指令集CPU 1.1.2. CIS ...

  4. C++ 统计输入的句子有多少英文字母

    // ConsoleApplication1.cpp: 定义控制台应用程序的入口点.//#include "stdafx.h"#include <iostream>#i ...

  5. Redis集群,备份,哨兵机制

    原文:https://blog.csdn.net/zy345293721/article/details/87536144 1.集群        先来简单了解下redis中提供的集群策略, 虽然re ...

  6. win10上安装redis

    1.下载安装包: 下载地址: 链接:https://pan.baidu.com/s/1oGPrfQJvFz-fX_KNcTTNUw 提取码:eake 2.在适合的位置创建一个文件夹,并将下载到的压缩包 ...

  7. 如何使用js在移动端和PC端居中

    在手机移动端和PC端控制居中是一个很蛋痛的问题,因为屏幕宽度在变化,所以就不要写死样式,那么我想用JS来控制,灵活的控制宽度,需要注意这三个时候: (1)首先需要在页面刚加载的时候就调用此函数, (2 ...

  8. .net WebApi使用swagger 美化接口文档

    本文将一步步演示如何用swagger美化WebApi接口文档,为接口文档添加接口名称说明,为请求参数和返回数据结构字段含义添加注释说明 一.为WebApi项目安装Swagger 首先我们新建一个Web ...

  9. Oracle 查询 in条件个数大于1000的解决方案

    Oracle 查询 in条件个数大于1000的解决方案,我所了解的有如下四种: 1. 把in分组再or: 思路:如果list的长度为2000,可以500个分一组,就有4个组,这4个组之间再or即可. ...

  10. 线性渐变css

    从上到下的线性渐变: #grad { background: -webkit-linear-gradient(red, blue); /* Safari 5.1 - 6.0 */ background ...