P3224 [HNOI2012]永无乡(平衡树合并)
题目描述
永无乡包含 nn 座岛,编号从 11 到 nn ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 nn 座岛排名,名次用 11 到 nn 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛到达另一个岛。如果从岛 aa 出发经过若干座(含 00 座)桥可以 到达岛 bb ,则称岛 aa 和岛 bb 是连通的。
现在有两种操作:
B x y 表示在岛 xx 与岛 yy 之间修建一座新桥。
Q x k 表示询问当前与岛 xx 连通的所有岛中第 kk 重要的是哪座岛,即所有与岛 xx 连通的岛中重要度排名第 kk 小的岛是哪座,请你输出那个岛的编号。
输入输出格式
输入格式:
第一行是用空格隔开的两个正整数 nn 和 mm ,分别表示岛的个数以及一开始存在的桥数。
接下来的一行是用空格隔开的 nn 个数,依次描述从岛 11 到岛 nn 的重要度排名。随后的 mm 行每行是用空格隔开的两个正整数 a_iai 和 b_ibi ,表示一开始就存在一座连接岛 a_iai 和岛 b_ibi 的桥。
后面剩下的部分描述操作,该部分的第一行是一个正整数 qq ,表示一共有 qq 个操作,接下来的 qq 行依次描述每个操作,操作的 格式如上所述,以大写字母 QQ 或 BB 开始,后面跟两个不超过 nn 的正整数,字母与数字以及两个数字之间用空格隔开。
输出格式:
对于每个 Q x k 操作都要依次输出一行,其中包含一个整数,表示所询问岛屿的编号。如果该岛屿不存在,则输出 -1−1 。
对于 20% 的数据
n \leq 1000, q \leq 1000n≤1000,q≤1000
对于 100% 的数据 n \leq 100000, m \leq n, q \leq 300000
n≤100000,m≤n,q≤300000
思路平衡树合并 把两个平衡树中小的那个拆开每一个加入到大的平衡树中
细节 本蒟蒻在这个地方出错了 2个平衡树用并差集合并后 其父节点既不是x也不是y也不是 find(x)也不是find(y) 是小的平衡树想大的平衡树里加的最后一个元素 那个元素是新的平衡树的 新的根节点
#include<iostream>
#include<cstring>
#include<stdio.h>
using namespace std;
const int maxn = +;
int f[maxn],val[maxn];
void init(){for(int i=;i<maxn;i++)f[i]=i;}
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
int fa[maxn],ch[maxn][],root,siz[maxn];
int data[maxn];
void pushup(int x){siz[x]=siz[ch[x][]]+siz[ch[x][]]+;}
void pushdown(int x){}
void rorate(int x){
int f=fa[x],df=fa[f],kind=ch[fa[x]][]==x;
pushdown(f),pushdown(x);
ch[f][kind]=ch[x][kind^];fa[ch[f][kind]]=f;
ch[x][kind^]=f;fa[f]=x;fa[x]=df;
if(df)ch[df][ch[df][]==f]=x;
pushup(f);pushup(x);
}
void splay(int x,int tar){
for(int f;(f=fa[x])!=tar;rorate(x))
if(fa[f]!=tar){
if((ch[fa[f]][]==f)==(ch[fa[x]][]==x))
rorate(f);
else rorate(x);
}
if(!tar)root=x;
}
void insert(int x,int u)
{
int ff=;
while(u){ff=u;u=ch[u][val[x]>val[u]];}
if(ff)ch[ff][val[x]>val[ff]]=x;
fa[x]=ff;siz[x]=;
ch[x][]=ch[x][]=;
splay(x,);
}
int temdata[maxn],cnt=;
void getall(int x){
if(ch[x][])getall(ch[x][]);
temdata[cnt++]=x;
if(ch[x][])getall(ch[x][]);
}
void merge(int x,int y)
{
if(find(x)==find(y))return;
x=find(x),y=find(y);
if(siz[x]<siz[y])swap(x,y);
cnt=;getall(y);
for(int i=;i<cnt;i++)insert(temdata[i],x);
f[x]=f[y]=temdata[cnt-];
}
int find_k(int x,int k){
if(siz[x]<k)return -;
if(siz[ch[x][]]+==k)return x;
if(siz[ch[x][]]>=k)return find_k(ch[x][],k);
return find_k(ch[x][],k-siz[ch[x][]]-);
}
int main()
{
init();
for(int i=;i<maxn;i++)siz[i]=;
int N,M,Q,x,y;char op[];
scanf("%d%d",&N,&M);
for(int i=;i<=N;i++)scanf("%d",val+i);
while(M--){
scanf("%d%d",&x,&y);
merge(x,y);
}
scanf("%d",&Q);
while(Q--){
scanf("%s%d%d",op,&x,&y);
if(op[]=='Q')printf("%d\n",find_k(find(x),y));
else merge(x,y);
}
return ;
}
P3224 [HNOI2012]永无乡(平衡树合并)的更多相关文章
- 线段树合并+并查集 || BZOJ 2733: [HNOI2012]永无乡 || Luogu P3224 [HNOI2012]永无乡
题面:P3224 [HNOI2012]永无乡 题解: 随便写写 代码: #include<cstdio> #include<cstring> #include<iostr ...
- 洛谷 P3224 [HNOI2012]永无乡 解题报告
P3224 [HNOI2012]永无乡 题目描述 永无乡包含 \(n\) 座岛,编号从 \(1\) 到 \(n\) ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 \(n\) 座岛排名,名次用 ...
- P3224 [HNOI2012]永无乡 题解
P3224 [HNOI2012]永无乡 题解 题意概括 有若干集合,每个集合最初包含一个值,和一个编号1~n.两个操作:合并两个集合,查询包含值x的集合中第k大值最初的集合编号. 思路 维护集合之间关 ...
- bzoj2733 / P3224 [HNOI2012]永无乡(并查集+线段树合并)
[HNOI2012]永无乡 每个联通块的点集用动态开点线段树维护 并查集维护图 合并时把线段树也合并就好了. #include<iostream> #include<cstdio&g ...
- BZOJ 2733: [HNOI2012]永无乡 启发式合并treap
2733: [HNOI2012]永无乡 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...
- bzoj2733: [HNOI2012]永无乡 启发式合并
地址:http://www.lydsy.com/JudgeOnline/problem.php?id=2733 题目: 2733: [HNOI2012]永无乡 Time Limit: 10 Sec ...
- 洛谷P3224 [HNOI2012]永无乡(线段树合并+并查集)
题目描述 永无乡包含 nnn 座岛,编号从 111 到 nnn ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 nnn 座岛排名,名次用 111 到 nnn 来表示.某些岛之间由巨大的桥连接, ...
- 洛谷 P3224 [HNOI2012]永无乡
题面 永无乡包含 \(n\) 座岛,编号从 \(1\) 到 \(n\) ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 \(n\) 座岛排名,名次用 \(1\) 到 \(n\) 来表示.某些岛 ...
- 2018.08.11 洛谷P3224 [HNOI2012]永无乡(线段树合并)
传送门 给出n个带点权的点,支持连边和查询连通块第k大. 这个貌似就是一道线段树合并的裸板啊... 代码: #include<bits/stdc++.h> #define N 100005 ...
随机推荐
- Spring入门,使用Maven进行管理
一,使用maven创建项目原型 mvn archetype:generate 进入交互模式创建项目原型,根据网速不同,跳出设置选项的时间不定 第一个选项 直接Enter即可,表示使用默认值502,后面 ...
- python操作DB2数据库
#!/usr/bin/env python# -*- coding:utf-8 -*- ########################## excute python2.7.13# sudo pip ...
- Pyhton第八节 字典补充
Python 字典的基本元素是键值对(key-value), 每个键值对的key和value之间用:分割:每个键值对之间用,分割:整个键值对用花括号{}包围 字典内的键(key)必须唯一,值不需要唯一 ...
- JAXB读写xml
一.注解 在Java模型中的创建与 xml 文件对应的节点和属性需要用注解来表示 @XmlRootElement 作用:将一个Java类映射为一段XML的根节点参数: name 定义这个根节点 ...
- 【读书笔记】C/C++程序员面试秘籍
第一章 C/C++ 程序基础(共12题) 第二章 预处理.const.static.和 sizeof(共27题) 第三章 引用和指针(共39题) 第四章 字符串(共31题) 第五章 位运算与嵌入式编程 ...
- js中获取basePath
单独js文件中el不能获取,通过以下方式获取1 var location = (window.location+'').split('/'); var basePath = location[0]+' ...
- WPF ListBox 横向排列
WPF ListBox 横向排列 如果只是单纯的让ListBox可以横向配列,这样很简单,只需要更改ListBox的ItemsPanel模板就可以,例如: <ListBox><L ...
- html常用标签梳理
标签的语法 标签由英文尖括号<和>括起来,如<html>就是一个标签. html中的标签一般都是成对出现的,分开始标签和结束标签.结束标签比开始标签多了一个/. 如: (1)& ...
- 在delphi中执行javascript代码
有时做项目难免用到代码交叉调用,delphi中执行js就是一种,两种方法可用: 一.使用webbrower,比较麻烦 二.使用ScriptControl,简单方便: 1.首先 uses ComObj; ...
- shellcode加密与解密
// Encoder.cpp : Defines the entry point for the console application.// #include "stdafx.h" ...