【bzoj2733】[HNOI2012]永无乡 线段树合并
2024-08-29 10:36:26
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
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
2
5
1
2
题解
并查集维护+权值线段树合并就ok了。
脑残地方Wrong,还要了数据。
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<iostream> #define N 100007
#define M 2000007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
} int n,m,k,sz;
int id[N],fa[N],rt[N],a[N];
int ls[M],rs[M],siz[M]; int find(int num)
{
if (fa[num]!=num) fa[num]=find(fa[num]);
return fa[num];
}
void ins(int &p,int l,int r,int z)
{
if(!p)p=++sz;
if (l==r){siz[p]=;return;}
int mid=(l+r)>>;
if (z<=mid) ins(ls[p],l,mid,z);
else ins(rs[p],mid+,r,z);
siz[p]=siz[ls[p]]+siz[rs[p]];
}
int query(int p,int l,int r,int rank)
{
if (l==r) return l;
int mid=(l+r)>>;
if (rank<=siz[ls[p]])return query(ls[p],l,mid,rank);
else return query(rs[p],mid+,r,rank-siz[ls[p]]);
}
int merge(int x,int y)
{
if (!x)return y;
if (!y)return x;
ls[x]=merge(ls[x],ls[y]);
rs[x]=merge(rs[x],rs[y]);
siz[x]=siz[ls[x]]+siz[rs[x]];
return x;
}
int main()
{
freopen("fzy.in","r",stdin);
freopen("fzy.out","w",stdout); n=read(),m=read();
for (int i=;i<=n;i++) a[i]=read(),fa[i]=i;
for (int i=;i<=m;i++)
{
int u=read(),v=read();
int x=find(u),y=find(v);
fa[y]=x;
}
for (int i=;i<=n;i++)
{
ins(rt[find(i)],,n,a[i]);
id[a[i]]=i;//反向映射
}
m=read();
while(m--)
{
char ch[];scanf("%s",ch);
int x=read(),y=read();
if (ch[]=='Q')
{
int p=find(x);
if (siz[rt[p]]<y)printf("-1\n");
else printf("%d\n",id[query(rt[p],,n,y)]);
}
else
{
int p=find(x),q=find(y);
if (p!=q)
{
fa[p]=q;
rt[q]=merge(rt[p],rt[q]);
}
}
}
}
最新文章
- Linux命令dos2unix 从windows转换到linux --- nuix2dos从linux转换到windows
- 关于 IE6、 IE7兼容性总结(转)
- ASP.NET中的GridView自带的编辑更新功能
- jQuery 中 offset()方法与用position()的区别
- 2015GitWebRTC编译实录10
- 【转】关于.net framework4.0以及4.5安装失败,“安装时发生严重错误”……
- Jade之条件语句
- Linux内核分析——第七周学习笔记20135308
- Xcode 编辑时的爆炸效果
- 转:SELENIUM TIPS: CSS SELECTORS
- UVA 1351	 十三 String Compression
- spark sql 访问hive数据时找不mysql的解决方法
- PHP 小代码
- Python学习--20 Web开发
- SpringMVC简单配置
- oracle状态
- Codeforces Round #403 (Div. 1, based on Technocup 2017 Finals)
- 去除html标记和替换script标记
- C# .NET XML 序列化为对象,反序列化
- Chapter6_访问权限控制_访问权限修饰词
热门文章
- Windows定时任务管理以及服务管理
- Codeforces Round #318 (Div. 2) C 	 Bear and Poker (数学)
- UVa 12219 Common Subexpression Elimination (stl,模拟,实现)
- UVA 10003 cuting sticks 切木棍 (区间dp)
- (三)VMware harbor使用http访问
- 前端知识点总结——HTML
- python之道07
- mysql存储引擎中InnoDB与Myisam的区别及应用场景
- cmake 指定输出目录
- 如何禁用Visual Studio的Browser Link功能