bzoj2733【hnoi2012】永无乡
2015-11-24 17:48
417 查看
2733: [HNOI2012]永无乡
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1728 Solved: 907
[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 14 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
-12
5
1
2
HINT
Source
Treap+启发式合并+并查集。每次将节点数少的平衡树暴力插入到另一个平衡树中,并用并查集维护。#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<cstdlib> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define LL long long #define pa pair<int,int> #define MAXN 100100 using namespace std; struct tree_type { int l,r,s,rnd,v; }t[MAXN]; int n,m,q,x,y,p[MAXN]; char ch; int read() { int ret=0,flag=1; char ch=getchar(); while (ch<'0'||ch>'9') { if (ch=='-') flag=-1; ch=getchar(); } while (ch>='0'&&ch<='9') { ret=ret*10+ch-'0'; ch=getchar(); } return ret*flag; } void rturn(int &k) { int tmp=t[k].l; t[k].l=t[tmp].r; t[tmp].r=k; t[tmp].s=t[k].s; t[k].s=t[t[k].l].s+t[t[k].r].s+1; k=tmp; } void lturn(int &k) { int tmp=t[k].r; t[k].r=t[tmp].l; t[tmp].l=k; t[tmp].s=t[k].s; t[k].s=t[t[k].l].s+t[t[k].r].s+1; k=tmp; } void ins(int &k,int &x) { if (!k) { k=x; t[k].s=1; t[k].l=t[k].r=0; t[k].rnd=rand(); return; } t[k].s++; if (t[x].v<t[k].v) { ins(t[k].l,x); if (t[t[k].l].rnd<t[k].rnd) rturn(k); } else { ins(t[k].r,x); if (t[t[k].r].rnd<t[k].rnd) lturn(k); } } int find(int x) { return p[x]==x?x:p[x]=find(p[x]); } void merge(int x,int y) { if (!y) return; merge(x,t[y].l); merge(x,t[y].r); ins(x,y); } void solvemerge(int x,int y) { int fx=find(x),fy=find(y); if (t[fx].s<t[fy].s) swap(fx,fy); p[fy]=fx; merge(fx,fy); } int getans(int k,int x) { int ln=t[t[k].l].s; if (ln+1==x) return k; else if (ln>=x) return getans(t[k].l,x); else return getans(t[k].r,x-ln-1); } int main() { n=read(); m=read(); F(i,1,n) { t[i].v=read(); t[i].s=1; t[i].l=t[i].r=0; p[i]=i; } F(i,1,m) { x=read(); y=read(); solvemerge(x,y); } q=read(); F(i,1,q) { ch=getchar();while (ch!='B'&&ch!='Q') ch=getchar(); x=read();y=read(); if (ch=='B') solvemerge(x,y); else { int fx=find(x); if (t[fx].s<y) puts("-1"); else printf("%d\n",getans(fx,y)); } } }
相关文章推荐
- samba共享线上实测
- Oracle创建临时表:CREATE GLOBAL TEMPORARY TABLE
- Android学习笔记系列开篇
- iOS中的urlString里面有时含有中文,nsstring延展
- 你真的会使用Chrome开发者工具吗?
- 1-1 07:输出浮点数
- java异常
- 推荐10个很棒的AngularJS学习指南
- Android中notifyDataSetInvalidated()和notifyDataSetChanged()的区别
- Java线程中锁的问题
- Oracle中,日期相加减换算日时分秒
- 数据链路层—三个基本问题
- Maven中的dependencyManagement和dependencies区别
- AngularJS控制器controller如何通信?
- 多线程问题
- VisualStudio 调试Linux
- 数据结构和算法之图---图的遍历之深度搜索dfs
- Lua5.1中的API函数
- linux下安装jdk和tomcat
- 如何用原生PHP GET到一个数组