题目描述

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

现在有两种操作:

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

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

输入输出格式

输入格式:

第一行是用空格隔开的两个正整数 nnn 和 mmm ,分别表示岛的个数以及一开始存在的桥数。

接下来的一行是用空格隔开的 nnn 个数,依次描述从岛 111 到岛 nnn 的重要度排名。随后的 mmm 行每行是用空格隔开的两个正整数 aia_iai​ 和 bib_ibi​ ,表示一开始就存在一座连接岛 aia_iai​ 和岛 bib_ibi​ 的桥。

后面剩下的部分描述操作,该部分的第一行是一个正整数 qqq ,表示一共有 qqq 个操作,接下来的 qqq 行依次描述每个操作,操作的 格式如上所述,以大写字母 QQQ 或 BBB 开始,后面跟两个不超过 nnn 的正整数,字母与数字以及两个数字之间用空格隔开。

输出格式:

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

说明

对于 20% 的数据 n≤1000,q≤1000n \leq 1000, q \leq 1000n≤1000,q≤1000

对于 100% 的数据 n≤100000,m≤n,q≤300000n \leq 100000, m \leq n, q \leq 300000 n≤100000,m≤n,q≤300000

题解:因为只有新增的桥,我们会想到并查集,问题转化成如何求一个并查集里的k小值,怎么办呢?当然是线段树合并了!我们在将x搞成y的父亲是顺便把y的线段树合并到x上就可以啦,接着就是权值线段树查询k小值的内容,显然不用再讲了。

代码如下:

#include<bits/stdc++.h>
#define lson tr[now].l
#define rson tr[now].r
using namespace std; struct tree
{
int l,r,sum;
}tr[]; int q,n,m,cnt,im[],wim[],f[],rt[]; int push_up(int now)
{
tr[now].sum=tr[lson].sum+tr[rson].sum;
} int update(int &now,int l,int r,int pos,int val)
{
if(!now) now=++cnt;
if(l==r)
{
tr[now].sum+=val;
return ;
}
int mid=(l+r)>>;
if(pos<=mid) update(lson,l,mid,pos,val);
else update(rson,mid+,r,pos,val);
push_up(now);
} int merge(int a,int b,int l,int r)
{
if(!a) return b;
if(!b) return a;
if(l==r)
{
tr[a].sum+=tr[b].sum;
return a;
}
int mid=(l+r)>>;
tr[a].l=merge(tr[a].l,tr[b].l,l,mid);
tr[a].r=merge(tr[a].r,tr[b].r,mid+,r);
push_up(a);
return a;
} int kth(int now,int l,int r,int k)
{
if(l==r) return l;
int mid=(l+r)>>;
if(tr[lson].sum>=k) return kth(lson,l,mid,k);
else return kth(rson,mid+,r,k-tr[lson].sum);
} int init()
{
for(int i=;i<=;i++)
{
f[i]=i;
}
} int find(int x)
{
if(f[x]==x) return x;
return f[x]=find(f[x]);
} int union_(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx==fy) return ;
f[fx]=fy;
merge(rt[fy],rt[fx],,);
} int print(int now)
{
if(lson) print(lson);
if(rson) print(rson);
printf("%d ",tr[now].sum);
} int solve(int v,int k)
{
int fv=find(v),ans;
if(tr[rt[fv]].sum<k) return puts("-1"),;
else ans=kth(rt[fv],,,k);
printf("%d\n",wim[ans]);
} int main()
{
init();
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) rt[i]=i,cnt++;
for(int i=;i<=n;i++)
{
scanf("%d",&im[i]);
wim[im[i]]=i;
update(rt[i],,,im[i],);
}
int from,to;
for(int i=;i<=m;i++)
{
scanf("%d%d",&from,&to);
union_(from,to);
}
char op[];
scanf("%d",&q);
while(q--)
{
scanf("%s %d %d",op,&from,&to);
if(op[]=='Q') solve(from,to);
if(op[]=='B') union_(from,to);
}
}

洛谷P3224 [HNOI2012]永无乡(线段树合并+并查集)的更多相关文章

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

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

  2. 洛谷 P3224 [HNOI2012]永无乡 解题报告

    P3224 [HNOI2012]永无乡 题目描述 永无乡包含 \(n\) 座岛,编号从 \(1\) 到 \(n\) ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 \(n\) 座岛排名,名次用 ...

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

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

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

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

  5. 2018.08.11 洛谷P3224 [HNOI2012]永无乡(线段树合并)

    传送门 给出n个带点权的点,支持连边和查询连通块第k大. 这个貌似就是一道线段树合并的裸板啊... 代码: #include<bits/stdc++.h> #define N 100005 ...

  6. 洛谷 P3224 [HNOI2012]永无乡

    题面 永无乡包含 \(n\) 座岛,编号从 \(1\) 到 \(n\) ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 \(n\) 座岛排名,名次用 \(1\) 到 \(n\) 来表示.某些岛 ...

  7. [洛谷P3224][HNOI2012]永无乡

    题目大意:给你$n$个点,每个点有权值$k$,现有两种操作: 1. $B\;x\;y:$将$x,y$所在联通块合并2. $Q\;x\;k:$查询第$x$个点所在联通块权值第$k$小是哪个数 题解:线段 ...

  8. bzoj 2733 : [HNOI2012]永无乡 (线段树合并)

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

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

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

随机推荐

  1. python 书籍推荐 一

    最近"瑞丽模特学Python"的热点牵动了大江南北程序员的心,有人说这是炒作,也有人说这是推广Python的爆点...我嘿嘿一笑,美女就是美女,眼光那是杠杠的,不仅人美,学的语言也 ...

  2. maven下载源代码,中文注释乱码的处理方法

    通过maven下载的源码,如果有注释是中文的话,一般会有乱码问题,解决办法如下: Window -> Preferences -> Content Types -> Text -&g ...

  3. java 面向对象 — 继承

    继承中的构造方法,先执行父类中的构造方法,然后执行子类中的构造方法 继承中的属性,最后执行的属性 覆盖前面的属性 因为是开辟了 两个内存空间,所以相比较是不同的. 如果想比较两个对象的值是否相同的话, ...

  4. POJ 1061 青蛙的约会(拓展欧几里得求同余方程,解ax+by=c)

    青蛙的约会 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 122871   Accepted: 26147 Descript ...

  5. 安卓控件获取器uiautomatorviewer初体验:"unable to connect to the adb. check if adb is installed correctly"

    解决方法:转自:https://plus.google.com/108487870030743970488/posts/2TrMqs1ZGQv Challenge Accepted:1. Screen ...

  6. Sql Server-使用Sql Server自带的分词功能实现字段关键词提取(分词能力很低,慎用)

    “创建全文索引 启动服务 在SQL Server配置管理工具中,找到'SQL Full-text Filter Daemon Launcher'服务用本地用户启动. 创建全文目录 打开需要创建全文目录 ...

  7. python打造文件包含漏洞检测工具

    0x00前言: 做Hack the box的题.感觉那个平台得开个VIp 不然得凉.一天只能重置一次...mmp 做的那题毒药是文件包含漏洞的题,涉及到了某个工具 看的不错就开发了一个. 0x01代码 ...

  8. ansible 使用

    批量添加ssh免密 ansible mhc -m authorized_key -a "user=root key='{{ lookup('file','/root/.ssh/id_dsa. ...

  9. 手游热更新方案xLua开源:Unity3D下Lua编程解决方案

    C#下Lua编程支持 xLua为Unity. .Net. Mono等C#环境增加Lua脚本编程的能力,借助xLua,这些Lua代码可以方便的和C#相互调用. xLua的突破 xLua在功能.性能.易用 ...

  10. 微信小程序通讯录首字母索引效果,车辆品牌选择列表

    效果图: wxml代码: <block wx:for="{{list}}"> <view class='letter' id="letter{{inde ...