题目描述

永无乡包含 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]永无乡(平衡树合并)的更多相关文章

  1. 线段树合并+并查集 || BZOJ 2733: [HNOI2012]永无乡 || Luogu P3224 [HNOI2012]永无乡

    题面:P3224 [HNOI2012]永无乡 题解: 随便写写 代码: #include<cstdio> #include<cstring> #include<iostr ...

  2. 洛谷 P3224 [HNOI2012]永无乡 解题报告

    P3224 [HNOI2012]永无乡 题目描述 永无乡包含 \(n\) 座岛,编号从 \(1\) 到 \(n\) ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 \(n\) 座岛排名,名次用 ...

  3. P3224 [HNOI2012]永无乡 题解

    P3224 [HNOI2012]永无乡 题解 题意概括 有若干集合,每个集合最初包含一个值,和一个编号1~n.两个操作:合并两个集合,查询包含值x的集合中第k大值最初的集合编号. 思路 维护集合之间关 ...

  4. bzoj2733 / P3224 [HNOI2012]永无乡(并查集+线段树合并)

    [HNOI2012]永无乡 每个联通块的点集用动态开点线段树维护 并查集维护图 合并时把线段树也合并就好了. #include<iostream> #include<cstdio&g ...

  5. BZOJ 2733: [HNOI2012]永无乡 启发式合并treap

    2733: [HNOI2012]永无乡 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  6. bzoj2733: [HNOI2012]永无乡 启发式合并

    地址:http://www.lydsy.com/JudgeOnline/problem.php?id=2733 题目: 2733: [HNOI2012]永无乡 Time Limit: 10 Sec   ...

  7. 洛谷P3224 [HNOI2012]永无乡(线段树合并+并查集)

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

  8. 洛谷 P3224 [HNOI2012]永无乡

    题面 永无乡包含 \(n\) 座岛,编号从 \(1\) 到 \(n\) ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 \(n\) 座岛排名,名次用 \(1\) 到 \(n\) 来表示.某些岛 ...

  9. 2018.08.11 洛谷P3224 [HNOI2012]永无乡(线段树合并)

    传送门 给出n个带点权的点,支持连边和查询连通块第k大. 这个貌似就是一道线段树合并的裸板啊... 代码: #include<bits/stdc++.h> #define N 100005 ...

随机推荐

  1. zabbix监控linux内存

    通过free -m查看当前内存 可用内存:Available memory=free+buffers+cached,即31068=759+66+30243 已用内存:Used memory=used- ...

  2. docker--删除container和image

    docker的命令分两类Management Commands和Commands Management Commands是对docker里的对象进行管理的 [root@localhost docker ...

  3. 微服务-技术专区-链路追踪(pinpoint)-部署使用

    https://naver.github.io/pinpoint/ https://github.com/naver/pinpoint 背景 随着项目微服务的进行,微服务数量逐渐增加,服务间的调用也越 ...

  4. MVC中的自定义标签分页控件,仅供大家学习!!

    public static HtmlString ShowPageNavigate(this HtmlHelper htmlHelper, int currentPage, int pageSize, ...

  5. Javascript中的Date()对象

    创建一个指定的事件对象 需要在构造函数中传递一个表示时间的字符串作为参数例:var d2=new Date("8/27/2019"); 如果直接使用构造函数创建一个Date对象,则 ...

  6. navigator对象-了解

    navigator 对象包含有关浏览器的信息,它有很多属性,我们最常用的是 userAgent ,该属性可以返回由客户机发送服务器的 user-agent 头部的值 下面前段代码可以判断用户使用哪个终 ...

  7. C3P0连接池属性配置注释

    属性 解释 acquireIncrement 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数 默认为:3 acquireRetryAttempts 定义在从数据库获取新连接失败后重复尝试的次数 ...

  8. dubbo-源码阅读之Filter默认实现

    SPI配置的默认实现 cache=com.alibaba.dubbo.cache.filter.CacheFilter validation=com.alibaba.dubbo.validation. ...

  9. HDU-4044 树形背包dp好题

    不会做,题解是参考网上的.感觉这道题是到好题,使得我对树形背包dp更了解了. 有几个注意的点,直接给出代码,题解以及注意点都在注释里了. #include<bits/stdc++.h> u ...

  10. Codeforces 1155F 状压DP

    题意:给你一张图,问最少保留多少条边,使得这张图是边双联通分量. 思路:如果一个点集中的点已经是边双联通分量,那么从这个点集中的点x出发,经过若干个不是点集中的点,回到点集中的点y(x可能等于y),那 ...