P3224 [HNOI2012]永无乡
思路
平衡树+启发式合并
貌似也可以线段树合并
连边就是合并两个Treap,查询就是第k大
使用Treap,好写好调
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
int Nodecnt=0,root[100100*2],fa[100100*2],n,m,w_p[100100*2];
struct Node{
    int lson,rson,sz,val,ran,num;
}Treap[100100*2];
int find(int x){
    if(fa[x]==x)
        return x;
    else
        return fa[x]=find(fa[x]);
}
queue<int> q;
void throwin(int x){
    q.push(x);
}
int getnew(int val,int num){
    int o;
    if(q.size())
        o=q.front(),q.pop();
    else
        o=++Nodecnt;
    Treap[o].lson=Treap[o].rson=0;
    Treap[o].sz=1;
    Treap[o].ran=rand();
    Treap[o].val=val;
    Treap[o].num=num;
    return o;
}
void pushup(int o){
    Treap[o].sz=Treap[Treap[o].lson].sz+Treap[Treap[o].rson].sz+1;
}
void rorateL(int &o){
    int x=Treap[o].rson;
    Treap[o].rson=Treap[x].lson;
    Treap[x].lson=o;
    pushup(o);
    pushup(x);
    o=x;
}
void rorateR(int &o){
    int x=Treap[o].lson;
    Treap[o].lson=Treap[x].rson;
    Treap[x].rson=o;
    pushup(o);
    pushup(x);
    o=x;
}
void insert(int val,int num,int &o){
    if(!o){
        o=getnew(val,num);
        return;
    }
    Treap[o].sz++;
    if(val<=Treap[o].val){
        insert(val,num,Treap[o].lson);
        if(Treap[Treap[o].lson].ran<Treap[o].ran)
            rorateR(o);
    }
    else{
        insert(val,num,Treap[o].rson);
        if(Treap[Treap[o].rson].ran<Treap[o].ran)
            rorateL(o);
    }
}
int query(int val,int o){
    if(!o)
        return -1;
    if(val==Treap[Treap[o].lson].sz+1)
        return Treap[o].num;
    else if(val>Treap[Treap[o].lson].sz+1)
        return query(val-Treap[Treap[o].lson].sz-1,Treap[o].rson);
    else
        return query(val,Treap[o].lson);
}
void dfs(int &o,int to){
    if(!o)
        return;
    insert(Treap[o].val,Treap[o].num,root[to]);
    dfs(Treap[o].lson,to);
    dfs(Treap[o].rson,to);
    throwin(o);
    o=0;
}
int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&w_p[i]),fa[i]=i,insert(w_p[i],i,root[i]);
    for(int i=1;i<=m;i++){
        int a,b;
        scanf("%d %d",&a,&b);
        if(find(a)!=find(b)){
            if(Treap[find(a)].sz<Treap[find(b)].sz){
                dfs(root[find(a)],find(b));
                fa[find(a)]=find(b);
            }
            else{
                dfs(root[find(b)],find(a));
                fa[find(b)]=find(a);
            }
        }
    }
    int q;
    scanf("%d",&q);
    for(int i=1;i<=q;i++){
        char opt=getchar();
        while(opt!='B'&&opt!='Q')
            opt=getchar();
        int a,b;
        scanf("%d %d",&a,&b);
        if(opt=='B'){
            if(find(a)!=find(b)){
                if(Treap[find(a)].sz<Treap[find(b)].sz){
                    dfs(root[find(a)],find(b));
                    fa[find(a)]=find(b);
                }
                else{
                    dfs(root[find(b)],find(a));
                    fa[find(b)]=find(a);
                }
            }
        }
        else{
            printf("%d\n",query(b,root[find(a)]));
        }
    }
    return 0;
}
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 ... 
- 洛谷P3224 [HNOI2012]永无乡(线段树合并+并查集)
		题目描述 永无乡包含 nnn 座岛,编号从 111 到 nnn ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 nnn 座岛排名,名次用 111 到 nnn 来表示.某些岛之间由巨大的桥连接, ... 
- 洛谷 P3224 [HNOI2012]永无乡
		题面 永无乡包含 \(n\) 座岛,编号从 \(1\) 到 \(n\) ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 \(n\) 座岛排名,名次用 \(1\) 到 \(n\) 来表示.某些岛 ... 
- P3224 [HNOI2012]永无乡(平衡树合并)
		题目描述 永无乡包含 nn 座岛,编号从 11 到 nn ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 nn 座岛排名,名次用 11 到 nn 来表示.某些岛之间由巨大的桥连接,通过桥可以从 ... 
- [洛谷P3224][HNOI2012]永无乡
		题目大意:给你$n$个点,每个点有权值$k$,现有两种操作: 1. $B\;x\;y:$将$x,y$所在联通块合并2. $Q\;x\;k:$查询第$x$个点所在联通块权值第$k$小是哪个数 题解:线段 ... 
- 2018.08.11 洛谷P3224 [HNOI2012]永无乡(线段树合并)
		传送门 给出n个带点权的点,支持连边和查询连通块第k大. 这个貌似就是一道线段树合并的裸板啊... 代码: #include<bits/stdc++.h> #define N 100005 ... 
随机推荐
- div盒子水平居垂直中的几种方法
			div盒子水平居垂直中的几种方法<!DOCTYPE html><html> <head> <mete charset="ut ... 
- 学习MySQL过程中的随笔二
			MySQL深入学习: 视图 使用视图的目的:多次使用同一张临时表(或者已经存在的表) 视图只是一个虚拟表,其本质为[根据SQL语句获取动态的数据集,并为其命名],用户只需使用别名即可获得实时的 ... 
- C# 字典Dictionary
			Dictionary<TKey, TValue> 泛型类提供了从一组键到一组值的映射.通过键来检索值的速度是非常快的,接近于 O(1),这是因为 Dictionary<TKey, T ... 
- Median
			#include <stdio.h> #include <stdlib.h> #include <math.h> #define MAXSIZE 1000 int ... 
- Win2008 IIS7.5安装配置PHP7.3.2步骤,及500错误解决
			安装Visual C++运行库 根据 PHP 版本选择 VC++ 版本,缺少 VC++ 运行库会报500错误. php-7.1.28-nts-Win32-VC14-x64.zip VC14: Vi ... 
- 牛客随笔(c++)
			1.关于指针的字节大小: 当为32位系统时大小为4字节,64位系统时大小为8字节: #include<iostream> using namespace std; int main() { ... 
- 分享一段js,判断是否是在iPhone中的Safari浏览器打开的页面
			头部引用jquery包 将下面的一段js写在</body>的前面 <script type="text/javascript"> var ua = navi ... 
- mondodb和mysql的区别
			我想从安全性和数据量这两个方面进行阐述. mongodb与mysql命令对比 传统的关系数据库一般由数据库(database).表(table).记录(record)三个层次概念组成, MongoDB ... 
- 网络-02-端口号-linux端口详解大全
			端口详解 1 tcpmux TCP Port Service Multiplexer 传输控制协议端口服务多路开关选择器 2 compressnet Management Utility compr ... 
- liunx驱动----系统滴答时钟的使用
			2019-3-12系统滴答定时器中断使用 定义一个timer  其实就是使用系统的滴答定时器产生一个中断. 初始化timer init_timer函数 实现如下 void fastcall ini ... 
