2733: [HNOI2012]永无乡 - BZOJ
2014-04-21 08:53
232 查看
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
平衡树启发式合并
每次合并都把小的拆开,放到大的里面(听说数据很水,随机的,不旋转就可以过,写了一个,然后就pascal的rank1了)
还是正常一点写一个splay吧(不过常数有点大,所以是深度超过32才splay)
View Code
永无乡包含 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
平衡树启发式合并
每次合并都把小的拆开,放到大的里面(听说数据很水,随机的,不旋转就可以过,写了一个,然后就pascal的rank1了)
还是正常一点写一个splay吧(不过常数有点大,所以是深度超过32才splay)
const maxn=100010; dep=32; type node=record son:array[0..1]of longint; size,data,fa:longint; end; var tree:array[0..maxn]of node; f,root:array[0..maxn]of longint; n,m,q:longint; function find(x:longint):longint; begin if f[x]=x then exit(x); f[x]:=find(f[x]); exit(f[x]); end; procedure rotate(x,w:longint;var root:longint); var y:longint; begin y:=tree[x].fa; tree[y].son[w]:=tree[x].son[w xor 1]; if tree[x].son[w xor 1]<>0 then tree[tree[x].son[w xor 1]].fa:=y; tree[x].son[w xor 1]:=y; if y=root then root:=x else if tree[tree[y].fa].son[0]=y then tree[tree[y].fa].son[0]:=x else tree[tree[y].fa].son[1]:=x; tree[x].fa:=tree[y].fa; tree[y].fa:=x; tree[y].size:=tree[tree[y].son[0]].size+tree[tree[y].son[1]].size+1; end; procedure splay(x:longint;var root:longint); var y:longint; begin while root<>x do begin y:=tree[x].fa; if y=root then if tree[y].son[0]=x then rotate(x,0,root) else rotate(x,1,root) else if tree[tree[y].fa].son[0]=y then if tree[y].son[0]=x then begin rotate(y,0,root); rotate(x,0,root); end else begin rotate(x,1,root); rotate(x,0,root); end else if tree[y].son[0]=x then begin rotate(x,0,root); rotate(x,1,root); end else begin rotate(y,1,root); rotate(x,1,root); end; end; tree[x].size:=tree[tree[x].son[0]].size+tree[tree[x].son[1]].size+1; end; procedure insert(x:longint;var root:longint); var now,step:longint; begin now:=root; step:=0; while true do begin inc(step); inc(tree[now].size); if tree[x].data<tree[now].data then if tree[now].son[0]=0 then break else now:=tree[now].son[0] else if tree[now].son[1]=0 then break else now:=tree[now].son[1]; end; if tree[x].data<tree[now].data then tree[now].son[0]:=x else tree[now].son[1]:=x; tree[x].size:=1; tree[x].son[0]:=0; tree[x].son[1]:=0; tree[x].fa:=now; if step>dep then splay(x,root); end; procedure dfs(x:longint;var root:longint); begin with tree[x] do begin if son[0]<>0 then dfs(son[0],root); if son[1]<>0 then dfs(son[1],root); insert(x,root); end; end; procedure union(x,y:longint); var u,v:longint; begin u:=find(x); v:=find(y); if u=v then exit; if tree[root[u]].size<tree[root[v]].size then begin dfs(root[u],root[v]); f[u]:=v; end else begin dfs(root[v],root[u]); f[v]:=u; end; end; procedure init; var i,x,y:longint; begin read(n,m); for i:=1 to n do begin f[i]:=i; root[i]:=i; tree[i].size:=1; end; for i:=1 to n do read(tree[i].data); for i:=1 to m do begin read(x,y); union(x,y); end; end; function ans(k:longint;var root:longint):longint; var now,step:longint; begin now:=root; step:=0; if k>tree[now].size then exit(-1); while true do begin inc(step); if k=tree[tree[now].son[0]].size+1 then begin if step>dep then splay(now,root); exit(now); end; if k<=tree[tree[now].son[0]].size then now:=tree[now].son[0] else begin dec(k,tree[tree[now].son[0]].size+1); now:=tree[now].son[1]; end; end; end; procedure work; var i,x,y:longint; c:char; begin readln(q); for i:=1 to q do begin readln(c,x,y); if c='Q' then begin if (x>n) or (x<1) then writeln(-1) else writeln(ans(y,root[find(x)])); end else union(x,y); end; end; begin init; work; end.
View Code
相关文章推荐
- 自娱自乐~经典24点游戏
- qsort 的使用方法
- iptables基础知识.详解
- TCP/IP、Http、Socket的区别
- Linux系统中vim工具常用命令大全
- 数据库
- 五种开源协议的比较(BSD,Apache,GPL,LGPL,MIT) – 整理
- incident impendence coefficient
- 转载:C/C++关于string.h头文件和string类
- html中span
- linux网络编程之socket(十二):select函数的并发限制和 poll 函数应用举例
- 修改Windows Server 远程登录(远程桌面)最大连接数目
- 关于数据库绿色版的安装
- 关于数据库绿色版的安装
- 关于数据库绿色版的安装
- 关于数据库绿色版的安装
- 关于数据库绿色版的安装
- 关于数据库绿色版的安装
- 关于数据库绿色版的安装
- 关于数据库绿色版的安装