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. MS SQL SERVER搜索某个表的主键所在的列名

    原文:MS SQL SERVER搜索某个表的主键所在的列名 SELECT SYSCOLUMNS.name  FROM SYSCOLUMNS,SYSOBJECTS,SYSINDEXES,SYSINDEX ...

  2. WPF显示html的几种方法

    原文:WPF显示html的几种方法 客户希望系统在一些特定的条件下,界面上能显示用户自定义的格式和内容,格式和内容通过html指定. 基本上在wpf中显示html有以下四种方法. 1.       W ...

  3. 零元学Expression Blend 4 - Chapter 2 入门界面简介

    原文:零元学Expression Blend 4 - Chapter 2 入门界面简介 在这篇教学我将会介绍Expression Blend 4的基本界面,虽然有些网站已经有做了介绍,为了整个教学的完 ...

  4. WinForm子线程调用主线程

    public Form1() { InitializeComponent(); Thread t = new Thread(ThreadWorker); t.Start(); } private vo ...

  5. oracle data guard配置dg_broker

    https://community.oracle.com/docs/DOC-1007327 本文主要包括以下内容: 1.  配置dg broker,需要完成以下几个工作: 在主备库配置静态监听注册,注 ...

  6. 让您的应用兼容 Android Oreo

    不知不觉Android Oreo已经发布几个月时间了,你的应用开始使用最新平台了吗?在应用迁移过程中是否遇到了一些棘手问题?你的Android应用兼容Oreo如何呢? 我们应该都知道,每一次重大升级, ...

  7. win32内存调用图

    https://msdn.microsoft.com/en-us/library/ms810603.aspxhttps://www.codeproject.com/Articles/14525/Hea ...

  8. ASP.NET Core Linux 发布

    这篇博客参考了以下文章: 1.http://www.cnblogs.com/ants/p/5732337.html 2.http://www.linuxidc.com/Linux/2016-11/13 ...

  9. QT中Dialog的使用(使用QStackedWidget维护页面切换)

    先看看效果图: pages.h #ifndef PAGES_H #define PAGES_H #include <QWidget> class ConfigurationPage : p ...

  10. 浅谈Linux(Centos7.4)环境下NTP服务器的构建

     一.软件环境 1.操作系统版本 [root@Geeklp201 etc]# cat /etc/redhat-release CentOS Linux release 7.4.1708 (Core ...