2733: [HNOI2012]永无乡

Time Limit: 20 Sec

Memory Limit: 256 MB

题目连接

http://www.lydsy.com/JudgeOnline/problem.php?id=2733

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

HINT

题意

题解:

启发式合并treap,直接套版咯。。。

合并就用并查集来维护,如果不在的话,就强行把小的treap直接暴力insert到大的treap里面就好了

然后再找第k大就好了

代码

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<vector>
#include<algorithm>
#include<ctime>
using namespace std;#define maxn 100005
int n,m,q;
//
struct TreeNode {TreeNode *L, *R;int num;int size;int pri;int key;
};
TreeNode nodes[maxn*30], stack[maxn*5];
TreeNode *null;
int C, Top;void init() {C = 0; Top = 0;null = &nodes[C++];null->L = null->R = null;null->pri = -0x7FFFFFFF;null->size = 0;null->key = 0;null->num = 0;
}struct Treap {TreeNode* root;vector<TreeNode*> list;void init() {root = null;}void toArrayList(TreeNode* root) {if (root != null) {toArrayList(root->L);list.push_back(root);toArrayList(root->R);}}TreeNode* newNode(int key, int num) {TreeNode* ret;if (Top)ret = &stack[--Top];else ret = &nodes[++C];ret->L = ret->R = null;ret->key = key;ret->pri = rand();ret->num = num;ret->size = num;return ret;}TreeNode* merge(TreeNode* A , TreeNode* B) {//合并if (A == null)return B;if (B == null)return A;if (A->pri < B->pri) {A->R = merge(A->R, B);pushUp(A);return A;} else {B->L = merge(A, B->L);pushUp(B);return B;}}pair<TreeNode*, TreeNode*> split(TreeNode* root, int key) {//分裂pair<TreeNode*, TreeNode*> tmp;if (root == null) {tmp = make_pair(null, null);return tmp;}if (key <= root->key) {tmp = split(root->L, key);root->L = tmp.second;pushUp(root);tmp.second = root;return tmp;} else {tmp = split(root->R, key);root->R = tmp.first;pushUp(root);tmp.first = root;return tmp;}}TreeNode* upperBound(TreeNode* root, int key) {TreeNode* ans = null;TreeNode* i = root;while (i != null) {if (key < i->key) {ans = i;i = i->L;} else {i = i->R;}}return ans;}TreeNode* lowerBound(TreeNode* root, int key) {TreeNode* ans = null;TreeNode* i = root;while (i != null) {if (key < i->key) {i = i->L;} else {ans = i;i = i->R;}}return ans;}bool contains(TreeNode* root, int key) {if (root == null)return false;if (key == root->key)return true;else if (key < root->key)return contains(root->L, key);elsereturn contains(root->R, key);}void insert(TreeNode* root, int key, int num) {if (key < root->key)insert(root->L, key, num);else if (key == root->key)root->num += num;elseinsert(root->R, key, num);pushUp(root);}void insert(int key, int num) {if (contains(root, key)) {insert(root, key, num);return ;}pair<TreeNode*, TreeNode*> tmp = split(root, key);TreeNode* node = newNode(key, num);root = merge(merge(tmp.first, node), tmp.second);}void del(int key) {pair<TreeNode*, TreeNode*> tmp = split(root, key);TreeNode* node = upperBound(tmp.second, key);if (node == null)root = tmp.first;elseroot = merge(tmp.first, split(tmp.second, node->key).second);}void del(TreeNode* root, int key) {if (!contains(root, key))return ;if (key < root->key)del(root->L, key);else if (key == root->key) {root->num--;if (root->num == 0)del(key);} else {del(root->R, key);}pushUp(root);}TreeNode* select(TreeNode* root, int k) {if (k <= root->L->size)return select(root->L, k);else if (k >= root->L->size + 1 && k <= root->L->size + root->num)return root;elsereturn select(root->R, k-root->L->size-root->num);}int getMin(TreeNode* root, int key) {if (key < root->key)return getMin(root->L, key);else if (key == root->key)return root->L->size + root->num;elsereturn root->L->size + root->num + getMin(root->R, key);}int getMax(TreeNode* root, int key) {if (key < root->key)return root->R->size + root->num + getMax(root->L, key);else if (key == root->key)return root->R->size + root->num;elsereturn getMax(root->R, key);}int size() {return root->size;}void visit(TreeNode* root) {if (root != null) {printf("key: %d num: %d size: %d\n", root->key, root->num, root->size);visit(root->L);visit(root->R);}}void pushUp(TreeNode* x) {x->size = x->L->size + x->R->size + x->num;}
};//
int fa[maxn];
Treap tr[maxn];
int val[maxn],Hash[maxn];
int fi(int x)
{if(x!=fa[x])fa[x]=fi(fa[x]);return fa[x];
}
void uni(int x,int y)
{x = fi(x),y = fi(y);if(x!=y){if(tr[x].size()>tr[y].size())swap(x,y);fa[x]=y;tr[x].list.clear();tr[x].toArrayList(tr[x].root);for(int i=0;i<tr[x].list.size();i++){TreeNode* tmp = tr[x].list[i];tr[y].insert(tmp->key,tmp->num);}}
}
int query(int x,int k)
{x = fi(x);if(tr[x].size()<k)return -1;else return tr[x].select(tr[x].root,k)->key;
}
int main()
{init();scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){tr[i].init();fa[i]=i;scanf("%d",&val[i]);Hash[val[i]]=i;tr[i].insert(val[i],1);}for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);uni(x,y);}scanf("%d",&q);for(int i=0;i<q;i++){char s[10];scanf("%s",&s);int x,y;scanf("%d%d",&x,&y);if(s[0]=='B'){uni(x,y);}else{int p = query(x,y);if(p==-1)printf("-1\n");else printf("%d\n",Hash[p]);}}
}

转载于:https://www.cnblogs.com/qscqesze/p/4969342.html

BZOJ 2733: [HNOI2012]永无乡 启发式合并treap相关推荐

  1. BZOJ 2733: [HNOI2012]永无乡 [splay启发式合并]

    2733: [HNOI2012]永无乡 题意:加边,询问一个连通块中k小值 终于写了一下splay启发式合并 本题直接splay上一个节点对应图上一个点就可以了 并查集维护连通性 合并的时候,把siz ...

  2. bzoj 2733: [HNOI2012]永无乡(线段树启发式合并)

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 3850  Solved: 2061 [Submit][Sta ...

  3. BZOJ[2733][HNOI2012]永无乡 Splay启发式合并

    题目链接 题目大意及线段树合并解法在这里 每合并两个点,将它俩启发式合并 启发式合并,即把小的暴力往大的那里插 说按前序遍历插复杂度会极其优越?? 第k大是平衡树基本操作 代码如下: #include ...

  4. BZOJ 2733: [HNOI2012]永无乡

    线段树合并 #include<cstdio> using namespace std; int cnt,F[100005],ls[2000005],rs[2000005],ID[20000 ...

  5. [Bzoj2733][Hnoi2012] 永无乡(BST)(Pb_ds tree)

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 4108  Solved: 2195 [Submit][Sta ...

  6. P3224 [HNOI2012]永无乡(并查集+权值线段树合并/平衡树)

    [HNOI2012]永无乡 Code1 权值线段树天然支持merge,线段树上二分求第k小 #include<bits/stdc++.h>using namespace std; usin ...

  7. 数据结构之fhq-treap——Chef and Sets,[HNOI2012]永无乡,Play with Chain,[NOI2005]维修数列(结构体版代码)

    因为非常板,所以主要是代码 Tyvj 1728 普通平衡树 Chef and Sets [HNOI2012]永无乡 Play with Chain [NOI2005]维修数列 题目很水,所以可能会出现 ...

  8. [BZOJ2733] [HNOI2012] 永无乡 (splay启发式合并)

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

  9. XSY1659 [HNOI2012]永无乡

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

最新文章

  1. 贪心:磁带最优存储与磁盘文件最优存储
  2. 语音购票、刷脸进站:上海联手阿里打造全球首个AI地铁之城
  3. Smooth Delivery:如何减少网络拥塞?
  4. 坐地铁可以刷学生卡吗_在沈阳办的公交卡能刷地铁吗?是学生卡,卡上写的是盛京通...
  5. 扩大缩小Linux物理分区大小
  6. sql server2008禁用远程连接
  7. InnoDB发展历史
  8. 利用开放定址法实现散列表的创建、插入、删除、查找操作_快速入门数据结构:散列表(上)...
  9. pytorch-数据增强的trick
  10. noi2018还没想好记
  11. 16个优秀网站设计网站
  12. 服务器配置与软件安装合集
  13. Vue组件通信原理剖析(三)provide/inject原理分析
  14. HTML文件无法显示IE图标的解决方法
  15. 减少过拟合的方法总结
  16. 3G到来将全面颠覆SP、CP游戏规则
  17. 前端Lottie动画实现方法
  18. 2021建筑施工电工(建筑特种作业)机考题库及建筑电工模拟试题
  19. C++11的消息总线
  20. vue TinyMCE编辑器增加字体

热门文章

  1. python重复字符串n次的函数_LeetCode_Python(3)_无重复字符的最长子串
  2. mysql数据库复制数据表时的风险
  3. python range倒序_Python算法学习之堆和堆排序
  4. 使用GDAL获取HDF等数据集中的图像
  5. mysql——数据库事务(C#代码)
  6. 谷歌和ESRI眼中的Web Mercator
  7. 鼓励玩家自创,大量的UGC能为手游续命吗?
  8. AnySDK项目实战教程
  9. [Stage3D]GPU渲染的喷泉粒子
  10. 修改linux端口22,修改LINUX 默认的22端口