博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[HNOI2012]永无乡
阅读量:6682 次
发布时间:2019-06-25

本文共 3197 字,大约阅读时间需要 10 分钟。

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

题解:

1.一道Splay的裸题,用并查集辅助判断一下是否在同一个集合中。

2.初始每一个点都是一棵Splay,维护树中k大值是Splay的正常操作。

3.每次并的时候用启发式合并,所以在Splay中要保存size参数表示字数的大小,然后每次将小的Splay放到大的Splay中。

1 //Never forget why you start  2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #define ll(x) (bst[x].child[0]) 9 #define rr(x) (bst[x].child[1]) 10 #define son(x,t) (bst[x].child[t]) 11 using namespace std; 12 int n,m; 13 struct Fa { 14 int fa[100005],cnt; 15 void clean() { 16 for(int i=1; i<=n; i++)fa[i]=i; 17 cnt=n; 18 } 19 int find(int x) { 20 if(fa[x]==x)return x; 21 else return fa[x]=find(fa[x]); 22 } 23 void merge(int x,int y) { 24 int p=find(x),q=find(y); 25 if(p!=q) { 26 fa[p]=q; 27 cnt--; 28 } 29 } 30 } fa;//并查集辅助判断是否联通 31 struct node { 32 int fa,child[2],x,size; 33 } bst[100005];//Splay结构体 34 void push_up(int r) { 35 bst[r].size=bst[son(r,0)].size+bst[son(r,1)].size+1; 36 }//统计size 37 void rotate(int r,int t) { 38 int fa=bst[r].fa; 39 son(fa,!t)=son(r,t);bst[son(r,t)].fa=fa; 40 son(bst[fa].fa,son(bst[fa].fa,1)==fa)=r;bst[r].fa=bst[fa].fa; 41 son(r,t)=fa;bst[fa].fa=r; 42 push_up(fa);push_up(r);//每次旋转都会使得大小发生变化,所以要重新更新 43 //注意这两个push_up不能写反 44 } 45 void Splay(int r,int goal) { 46 int fa=bst[r].fa; 47 while(fa!=goal) { 48 if(bst[fa].fa==goal)rotate(r,son(fa,0)==r); 49 else { 50 int t=son(bst[fa].fa,0)==fa; 51 if(son(fa,t)==r)rotate(r,!t),rotate(r,t); 52 else rotate(fa,t),rotate(r,t); 53 } 54 fa=bst[r].fa; 55 } 56 }//Splay树骚操作 57 int r; 58 void insert(int x,int root) { 59 while(1) { 60 bst[root].size++; 61 if(bst[x].x>bst[root].x) { 62 if(!son(root,1)) { 63 son(root,1)=x; 64 bst[x].fa=root; 65 Splay(x,0); 66 return; 67 } else root=son(root,1); 68 } else { 69 if(!son(root,0)) { 70 son(root,0)=x; 71 bst[x].fa=root; 72 Splay(x,0); 73 return; 74 } else root=son(root,0); 75 } 76 } 77 }//向Splay中插入一个点 78 void trash(int x,int y) { 79 if(!x)return; 80 trash(ll(x),y);trash(rr(x),y); 81 son(x,1)=son(x,0)=bst[x].size=bst[x].fa=0; 82 insert(x,r); 83 r=x; 84 }//将一棵Splay的每一个点分别插入到另一棵Splay 85 void merge(int u,int v) { 86 if(u==v)return; 87 Splay(u,0);Splay(v,0); 88 if(bst[u].size>bst[v].size)swap(u,v); 89 r=v; 90 trash(u,r); 91 }//启发式合并两棵Splay 92 int k_th(int a,int b) { 93 if(bst[a].size
b-1)return k_th(son(a,0),b); 96 if(bst[son(a,0)].size

 

转载于:https://www.cnblogs.com/huangdalaofighting/p/8260245.html

你可能感兴趣的文章
从“阿北的知识分享”新增视频模板消息推送开始说yii2队列
查看>>
类似表格的删除与添加
查看>>
Chrome 浏览器 Javascript 调试参考
查看>>
VueRouter基础
查看>>
Spring之旅 - 3.0、3.1、4.0导引
查看>>
聊聊我理解的ANSI C、ISO C、GNU C、POSIX C
查看>>
Django新增models和表的方法
查看>>
微信小程序入坑记录篇
查看>>
vue2.0学习笔记(第九讲)(vue-router实现路由)
查看>>
AppleScript脚本入门
查看>>
Windows环境下Jekyll+Github搭建个人博客
查看>>
windows下安装Logstash
查看>>
Hystrix使用
查看>>
最常用的正则表达式
查看>>
《啊哈!算法》-第 2 章:栈、队列、链表
查看>>
闲话JavaScript数据类型
查看>>
Facebook--Graphql 为什么功能这么强大?与开源数据库的结合分析
查看>>
用 ClojureScript 语法运行 React
查看>>
手摸手,带你用vue撸后台 系列四(vueAdmin 一个极简的后台基础模板)
查看>>
Composer的Autoload源码实现——注册与运行
查看>>