2733: [HNOI2012]永无乡

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 3955  Solved: 2112
[Submit][Status][Discuss]

Description

永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛。如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的。现在有两种操作:B x y 表示在岛 x 与岛 y 之间修建一座新桥。Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k 小的岛是哪 座,请你输出那个岛的编号。

Input

输入文件第一行是用空格隔开的两个正整数 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

Output

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

Sample Input

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

Sample Output

-1
2
5
1
2
  这道题当时第一眼觉得像是图论tarjan题,然后看到了求排名的操作,这就不得不考虑平衡树了,由于平衡树我只会SPLAY,不会无旋TREAP所以我就只讲SPLAY的了。
  这道题想到平衡树后就开始想合并操作,如果暴力合并最坏貌似是炸翻天的,一开始以为有什么神奇的打法,比如区间插入还自带平衡的黑科技之类的,结果同桌告诉我是启发式合并。所谓启发式合并就是暴力合并,只是有一个几乎所有人都想的到的剪枝,让小项去合并大项,时间自然会小不少。
  所以对于每一次合并我们只是dfs一边当前的小子树,然后就暴力合并就好了,其他操作照常。
 #pragma GCC optimze("O3")
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cmath>
#include<map>
#define N 100004
using namespace std;
int n,m,q,f[N],fa[N],size[N],ch[N][],data[N];
int find(int x)
{
if(f[x]==x)return x;
return f[x]=find(f[x]);
}
bool get(int x)
{
return x==ch[fa[x]][];
}
void update(int x)
{
if(x)
{
size[x]=;
if(ch[x][]) size[x]+=size[ch[x][]];
if(ch[x][]) size[x]+=size[ch[x][]];
}
}
void rotate(int x)
{
int faa=fa[x],ffa=fa[fa[x]];
int op=get(x);
ch[faa][op]=ch[x][op^];
fa[ch[faa][op]]=faa;
ch[x][op^]=faa;
fa[faa]=x;
fa[x]=ffa;
if(ffa)ch[ffa][ch[ffa][]==faa]=x;
update(faa);
update(x);
return;
}
void splay(int x)
{
for(int ff;ff=fa[x];rotate(x))
{
if(fa[ff])
rotate((get(x)==get(ff))?ff:x);
}
return;
}
int lart;
void insert(int x,int now,int faa)
{ if(now==)
{
fa[x]=faa;
if(data[x]<data[faa]) ch[faa][]=x;
else ch[faa][]=x;
splay(x);
lart=x;
return;
}
if(data[x]<data[now])insert(x,ch[now][],now);
else insert(x,ch[now][],now);
}
void dfs(int x,int y)
{
int le=ch[x][],ri=ch[x][];
ch[x][]=ch[x][]=;
insert(x,y,);
if(le)dfs(le,lart);
if(ri)dfs(ri,lart);
}
int get_rank(int x,int la)
{
if(la==size[ch[x][]]+)
return x;
if(la<=size[ch[x][]])
return get_rank(ch[x][],la);
else
return get_rank(ch[x][],la-size[ch[x][]]-);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%d",&data[i]);
f[i]=i;size[i]=;
}
for(int i=;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
int aa=find(x),bb=find(y);
if(aa==bb)continue;
f[aa]=bb;
splay(x),splay(y);
if(size[x]>size[y])
dfs(y,x);
else
dfs(x,y);
}
scanf("%d",&q);
char b[];
for(int i=;i<=q;i++)
{
scanf("%s",b);
int x,y;
scanf("%d%d",&x,&y);
if(b[]=='B')
{
int aa=find(x),bb=find(y);
if(aa==bb)continue;
f[aa]=bb;
splay(x),splay(y);
if(size[x]>size[y])
dfs(y,x);
else
dfs(x,y);
}
else
{
splay(x);
if(size[x]<y)printf("-1\n");
else
{
printf("%d\n",get_rank(x,y));
}
}
}
return ;
}

Bzoj 2733: [HNOI2012]永无乡 数组Splay+启发式合并的更多相关文章

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

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

  2. bzoj2733: [HNOI2012]永无乡(splay+启发式合并/线段树合并)

    这题之前写过线段树合并,今天复习Splay的时候想起这题,打算写一次Splay+启发式合并. 好爽!!! 写了长长的代码(其实也不长),只凭着下午的一点记忆(没背板子...),调了好久好久,过了样例, ...

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

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

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

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

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

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

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

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

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

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

  8. BZOJ2733 永无乡 【splay启发式合并】

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 4190  Solved: 2226 [Submit][Sta ...

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

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

随机推荐

  1. Android 9.0 Dialog不显示

    Tester报了一个bug,大概如下: 页面:Activity1 dialog1(半透明遮罩样式) Activity2 dialog2 场景:Activity1弹出dialog1,dialog1弹出a ...

  2. LINQ查询表达式---------from子句

    LINQ查询表达式---------from子句 LINQ的查询由3基本部分组成:获取数据源,创建查询,执行查询. //1.获取数据源 List<, , , , , }; //创建查询 var ...

  3. 三种方式配置Mac OS X的启动项

    在Mac OS X中,有三种方式来实现启动项的配置:1)Login Items:2)StartupItems:3)launchd daemon. 1.Login Items 打开System Pref ...

  4. C# 中使用OPenCV(Emgu)心得

    原文:C# 中使用OPenCV(Emgu)心得 首先介绍一下自己的情况,2010年的3月份开始接触学习C#编程,之前C#和OpenCV都是零基础,由于全都是自学进度比较慢,中间也走了不少弯路.进过三个 ...

  5. DELPHI之关于String的内存分配(引)

    在函数.过程或者方法中定义一个字符串变量时,由于我们知道在函数.过程或者方法中定义的变量为局部变量,它的内存 是在栈中分配的,但是这里有个小细节我们要注意,对于一个局部的字符串变量,它的大小为4字节, ...

  6. ThoughtWorks 面试备忘录

    ThoughtWorks 面试备忘录 前言 前段时间 ThoughtWorks 在网上和拉勾网合作搞了一次网络招聘,名为抛弃简历!让代码说话!,可谓赚足了眼球,很多程序猿纷纷摩拳擦掌.踊跃提交代码,在 ...

  7. 在本地安装RabbitMQ Server教程以及可能遇到的问题及解决办法

    1. Download latest erlang OTP platform from : erlang:http://www.erlang.org/download.html (The latest ...

  8. python正则表达式模块

    正则表达式是对字符串的最简约的规则的表述.python也有专门的正则表达式模块re. 正则表达式函数 释义 re.match() 从头开始匹配,匹配失败返回None,匹配成功可通过group(0)返回 ...

  9. Redis 学习笔记(篇二):字典

    字典 字典又称为符号表.关联数组或映射(map),是一种用于保存键值对(key-value)的数据结构. 那么 C 语言中有没有这样 key-value 型的内置数据结构呢? 答案:没有. 说起键值对 ...

  10. SpringBoot启动访问JSP页面,直接进入页面或者访问不到,报404,并且加载tomcat插件tomcat-embed-jasper也不行

    这个问题花费了两天的时间,解决路径: 我用的是SpringBoot1.5.2,SpringMVC和Spring,tomcat启动插件都是默认的版本,Spring是4.3.7,jdk是1.7.0_80, ...