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. Win8 Metro(C#)数字图像处理--2.39二值图像投影

    原文:Win8 Metro(C#)数字图像处理--2.39二值图像投影  [函数名称]   二值图像投影         ImageProjection(WriteableBitmap src) ...

  2. Python杂谈: 集合中union和update的区别(Python3.x)

    集合中union和update方法都是将多个可迭代的对象合并,但是返回的结果和对初始对象的影响却不一样 # union() 方法 - a.union(b) 将集合a和集合b取并集,并将并集作为一个新的 ...

  3. GIS基础软件及操作(九)

    原文 GIS基础软件及操作(九) 练习九.水文分析 水文分析:根据DEM提取河流网络,计算流水累积量.流向.根据指定的流域面积大小自动划分流域 水文分分析工具 (1)通过Arctoolbox:水文分析 ...

  4. 零元学Expression Blend 4 Chapter 22 以实作案例学习Frame及HyperlinkButton

    原文:零元学Expression Blend 4 Chapter 22 以实作案例学习Frame及HyperlinkButton 本章将教大家如何以实作善用Blend4的内建功能-「Frame」以及「 ...

  5. 微信小程序把玩(三十六)Storage API

    原文:微信小程序把玩(三十六)Storage API 其实这个存储在新建Demo的时候就已经用到了就是存储就是那个logs日志,数据存储主要分为同步和异步 异步存储方法: 存数据 wx.setStor ...

  6. oh my zsh安装

    引言 最近阿里云搞活动,整了一台服务器,作为Linux的爱好者,又免费,so.......当然不能错过了.以前看到好多炫酷的Linux界面,比如这样的:梦想中…… 通过各种方式得知这是Oh my zs ...

  7. 基于VUE实现的新闻后台管理系统-一

    基于VUE实现的新闻后台管理系统 前段时间拿到一个关于新闻后台的API,测试数据库使用SQLite,Restful服务是用Go写的,只要运行特定环境下的脚本(run.*)就会启动一个服务,依次后台为接 ...

  8. UWP中的消息提示框(一)

    不管什么平台,应用内难免会出现一些消息提示框,下面就来聊聊我在UWP里用到的消息提示框. 弹窗也可按是否需要用户操作促发一些逻辑进行分为两大类. 不需要用户干涉的一类: MessageDialog:操 ...

  9. Tobject 类解析

    TObject = class    //创建    constructor Create;    //释放    procedure Free;    //初始化实列    class functi ...

  10. 解决com.android.dex.DexException: Multiple dex files define Lcom/google/gson/JsonSerializer;

    我在开发Windows Azure的Mobile Service(隔天补上创建过程)的安卓客户端时,报出了com.android.dex.DexException: Multiple dex file ...