当前位置: 首页 > news >正文

【BZOJ】2733: [HNOI2012]永无乡

【题意】给定n个岛屿和排名,q次操作,连接两个岛屿或查询岛屿所在连通块第k小。

【算法】平衡树(treap)||线段树合并

对于每个连通块维护排名树,启发式合并(将size较小的树一一拆出来加入另一棵树)。

复杂度O(n log2n)。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<stack>
using namespace std;
const int maxn=100010;
struct tree{int l,r,rnd,sz,num,id;}t[maxn*2];
stack<int>s;
int rank[maxn],fa[maxn],root[maxn],n,m;
int read(){
    char c;int s=0,t=1;
    while(!isdigit(c=getchar()))if(c=='-')t=-1;
    do{s=s*10+c-'0';}while(isdigit(c=getchar()));
    return s*t;
}
void up(int k){t[k].sz=t[t[k].l].sz+1+t[t[k].r].sz;}
void rturn(int &k){
    int o=t[k].l;
    t[k].l=t[o].r;
    t[o].r=k;
    up(k);up(o);
    k=o;
}
void lturn(int &k){
    int o=t[k].r;
    t[k].r=t[o].l;
    t[o].l=k;
    up(k);up(o);
    k=o;
}
void insert(int &k,int x){
    if(!k){
        k=s.top();s.pop();
        t[k].rnd=rand();t[k].num=rank[x];
        t[k].sz=1;t[k].l=t[k].r=0;t[k].id=x;
        return;
    }
    t[k].sz++;
    if(rank[x]<t[k].num){
        insert(t[k].l,x);
        if(t[t[k].l].rnd<t[k].rnd)rturn(k);
    }
    else{
        insert(t[k].r,x);
        if(t[t[k].r].rnd<t[k].rnd)lturn(k);
    }
}
int getfa(int x){return fa[x]==x?x:fa[x]=getfa(fa[x]);}
void dfs(int k,int &x){
    if(!k)return;
    s.push(k);
    int L=t[k].l,R=t[k].r;
    insert(x,t[k].id);
    dfs(L,x);dfs(R,x);
}
void merge(int x,int y){
    x=getfa(x);y=getfa(y);
    if(x==y)return;
    if(t[root[x]].sz<t[root[y]].sz)swap(x,y);
    fa[y]=x;
    dfs(root[y],root[x]);
}
int find(int k,int x){
    if(x==t[t[k].l].sz+1)return t[k].id;
    else if(x<t[t[k].l].sz+1)return find(t[k].l,x);
    else return find(t[k].r,x-t[t[k].l].sz-1);
}
int main(){
    srand(233);
    n=read();m=read();
    for(int i=1;i<=n;i++)rank[i]=read();
    for(int i=n;i>=1;i--)s.push(i);
    for(int i=1;i<=n;i++)insert(root[i],i);
    for(int i=1;i<=n;i++)fa[i]=i;
    for(int i=1;i<=m;i++){
        int x=read(),y=read();
        merge(x,y);
    }
    int Q=read();
    char ch[10];
    for(int i=1;i<=Q;i++){
        scanf("%s",ch);
        int x=read(),y=read();
        if(ch[0]=='B')merge(x,y);
        else{
            if(t[root[getfa(x)]].sz>=y)printf("%d\n",find(root[fa[x]],y));//use root[]
            else printf("-1\n");
        }
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/onioncyc/p/7906118.html

相关文章:

  • 网络通信原理及要素
  • python脚本采集服务器数据通过API提交到django web服务器,然后展示在页面上
  • Linux下搭建NFS服务器
  • shell整理(38)===凯撒加密和解密
  • 使用embulk从Oracle抽取数据到trafodion
  • dubbo 服务中间件 的使用
  • [zabbix/自动发现规则]
  • 项目管理:项目中什么叫完成,传统瀑布开发与敏捷开发的完成标准是什么??...
  • php如何发post请求
  • let和var的一个问题
  • aix 查看占用内存高的进程
  • WIN7 U盘安装
  • [完美]原生JS获取浏览器版本判断--支持Edge,IE,Chrome,Firefox,Opera,Safari,以及各种使用Chrome和IE混合内核的浏览器...
  • MongoDB(课时10 数组)
  • vue+vuex+axios+echarts画一个动态更新的中国地图
  • .pyc 想到的一些问题
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • 【Leetcode】104. 二叉树的最大深度
  • C++类的相互关联
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • ECS应用管理最佳实践
  • iOS 颜色设置看我就够了
  • Java的Interrupt与线程中断
  • jdbc就是这么简单
  • jQuery(一)
  • js算法-归并排序(merge_sort)
  • JS学习笔记——闭包
  • Linux CTF 逆向入门
  • Spark VS Hadoop:两大大数据分析系统深度解读
  • 初识MongoDB分片
  • 大快搜索数据爬虫技术实例安装教学篇
  • 全栈开发——Linux
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 三栏布局总结
  • 深度解析利用ES6进行Promise封装总结
  • 什么软件可以提取视频中的音频制作成手机铃声
  • 项目实战-Api的解决方案
  • 带你开发类似Pokemon Go的AR游戏
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​Linux·i2c驱动架构​
  • #include到底该写在哪
  • %@ page import=%的用法
  • (Matalb时序预测)PSO-BP粒子群算法优化BP神经网络的多维时序回归预测
  • (Redis使用系列) Springboot 整合Redisson 实现分布式锁 七
  • (每日持续更新)jdk api之FileFilter基础、应用、实战
  • (四)JPA - JQPL 实现增删改查
  • (学习日记)2024.01.19
  • (转)大型网站的系统架构
  • ..回顾17,展望18
  • .apk 成为历史!
  • .apk文件,IIS不支持下载解决
  • .NET 分布式技术比较
  • .NET 将多个程序集合并成单一程序集的 4+3 种方法
  • .NET 同步与异步 之 原子操作和自旋锁(Interlocked、SpinLock)(九)
  • .NET命令行(CLI)常用命令