原题传送门

题意:给你N个带权点,一开始相互独立(每个点视为单独一个集合),有2种操作:1)合并2个集合;2)查询包含某元素集合内的权值第k小点编号。

解题思路:显然合并就是并查集,而查询则是平衡树实现。

考虑对每个集合开一棵平衡树,这样的话直接合并2棵平衡树的效率最坏是\( n \log n \)的,显然会TLE。

考虑使用启发式合并,这样就可以将合并的集合树的深度严格限制在\( \log n \)内,于是每次合并的效率就约为 \( \log^{2} n \)的。这样就不会TLE了。

时间效率:操作1:\( \log^{2} n \) ; 操作2: \( \log n \).

注意一下如果已经在一个集合内就不要合并了。

总复杂度:\( O( (m+q) \log^{2} n) \) / \( O(n) \).

AC代码:(1312ms/4688KB on BZOJ)

#include <stdio.h>
#define r register
#define MN 100005
#define getchar() (S==TT&&(TT=(S=BB)+fread(BB,1,1<<15,stdin),S==TT)?EOF:*S++)
char BB[<<],*S=BB,*TT=BB;
inline int read(){
r int x=,f=; r char ch=getchar();
while (ch<''||ch>'') f=ch=='-'?-:,ch=getchar();
while (ch>=''&&ch<='') x=(x<<)+(x<<)+ch-'',ch=getchar();
return x*f;
}inline int rad(){
static int x=;
return x^=x<<,x^=x>>,x^=x<<;
}
struct treap{
treap *ls,*rs;
int sz,val,ord,pri;
void combine(){
sz=;
if (ls!=NULL) sz+=ls->sz;
if (rs!=NULL) sz+=rs->sz;
}treap(int val,int ord):ord(ord),val(val){ls=rs=NULL,sz=,pri=rad();}
}*root[MN];
inline void lturn(treap* &x){r treap *y=x->rs; x->rs=y->ls; y->ls=x; y->sz=x->sz; x->combine(); x=y;}
inline void rturn(treap* &x){r treap *y=x->ls; x->ls=y->rs; y->rs=x; y->sz=x->sz; x->combine(); x=y;}
inline void Insert(treap* &x,int val,int ord){
if (x==NULL) {x=new treap(val,ord);return;}x->sz++;
if (val<x->val){Insert(x->ls,val,ord);if (x->ls->pri<x->pri) rturn(x);}
else{Insert(x->rs,val,ord);if (x->rs->pri<x->pri) lturn(x);}
}
inline void merge(treap* &o,treap* &x){
if (o==NULL) return;
merge(o->ls,x);merge(o->rs,x);
Insert(x,o->val,o->ord);
delete o;o=NULL;return;
}
inline int query(treap *x,int k){
if (x==NULL||k<||k>x->sz) return -;
if (x->ls==NULL){
if (k==) return x->ord;
return query(x->rs,k-);
}
if (k<=x->ls->sz) return query(x->ls,k);
if (k==x->ls->sz+) return x->ord;
return query(x->rs,k-x->ls->sz-);
}
int fa[MN],n,q;
inline int getfa(int x){return fa[x]?fa[x]=getfa(fa[x]):x;}
void init(){
n=read(),q=read();
for (int i=; i<=n; ++i) Insert(root[i],read(),i);
while(q--){
r int x=getfa(read()),y=getfa(read()); if (x==y) continue;
if (root[x]->sz<root[y]->sz) merge(root[x],root[y]),fa[x]=y;
else merge(root[y],root[x]),fa[y]=x;
}
}
void solve(){
q=read();while (q--){
r char op=getchar();while(op!='Q'&&op!='B') op=getchar();
r int x=read(),y=read();
if (op=='Q') printf("%d\n",query(root[getfa(x)],y));
else{
x=getfa(x),y=getfa(y); if (x==y) continue;
if (root[x]->sz<root[y]->sz) merge(root[x],root[y]),fa[x]=y;
else merge(root[y],root[x]),fa[y]=x;
}
}
}
int main(){init(); solve(); return ;}

【BZOJ2733】【HNOI2012】永无乡的更多相关文章

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

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

  2. bzoj2733: [HNOI2012]永无乡(splay)

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3778  Solved: 2020 Description 永 ...

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

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

  4. [bzoj2733][HNOI2012]永无乡_权值线段树_线段树合并

    永无乡 bzoj-2733 HNOI-2012 题目大意:题目链接. 注释:略. 想法: 它的查询操作非常友善,就是一个联通块内的$k$小值. 故此我们可以考虑每个联通块建一棵权值线段树. 这样的话每 ...

  5. BZOJ2733 [HNOI2012]永无乡 【线段树合并】

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

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

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

  7. BZOJ2733[HNOI2012]永无乡——线段树合并+并查集+启发式合并

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

  8. bzoj2733: [HNOI2012]永无乡 线段树合并

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

  9. BZOJ2733: [HNOI2012]永无乡(线段树合并)

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

  10. BZOJ2733 [HNOI2012]永无乡

    直接平衡树启发式合并就好了...貌似是个很高端的东西.. 貌似可以证明splay的启发式合并是均摊$O(nlogn)$的...而其他平衡树都不行,所以其他的复杂度都是$O(nlog^2n)的$的 所以 ...

随机推荐

  1. Alpha第十天

    Alpha第十天 听说 031502543 周龙荣(队长) 031502615 李家鹏 031502632 伍晨薇 031502637 张柽 031502639 郑秦 1.前言 任务分配是VV.ZQ. ...

  2. Beta冲刺 第六天

    Beta冲刺 第六天 1. 昨天的困难 1.对于设计模式的应用不熟悉,所以在应用上出现了很大的困难. 2.SSH中数据库的管理是用HQL语句实现的,所以在多表查询时出现了很大的问题. 3.页面结构太凌 ...

  3. selenium 爬虫

    from selenium import webdriver import time driver = webdriver.PhantomJS(executable_path="D:/pha ...

  4. GPUImage滤镜效果翻译

    #import"GPUImageBrightnessFilter.h"//亮度 #import"GPUImageExposureFilter.h"//曝光 #i ...

  5. loadrunner下载资源时步骤下载超时 (120 seconds) 已过期

    下载资源所用时间超过120秒时,就会报出这个错误,解决方法是设置加大超时时间 运行时设置(快捷键F4) Internet 协议--首选项--高级--选项--General--步骤下载超时(秒) 可以把 ...

  6. XML之自动生成类,添加,修改,删除类的属性

    1. class ClassHelperDemo { public static void Main() { #region 演示一:动态生成类. //生成一个类t. Type t = ClassHe ...

  7. href的理解

    您搜索的项目暂未上线,可直接<a style="color: #ff0000;" onclick="onlineTalk();" href="j ...

  8. C# 使用 GDI+ 画图

    最近做一个微信公众号服务,有一些简单的图片处理功能.主要就是用户在页面操作,前端做一些立刻显示的效果,然后提交保存时后端真正修改原图. 我们的后端是 ASP.NET,也就是 C# 语言了,C# 本身处 ...

  9. c 存储类型

    1,c语言中的存储类型(定义变量和函数的可见范围和生命周期)这些说明符放置在它们所修饰的类型之前.下面列出 C 程序中可用的存储类: auto register static extern 2,aut ...

  10. 智能合约语言 Solidity 教程系列9 - 错误处理

    这是Solidity教程系列文章第9篇介绍Solidity 错误处理. Solidity系列完整的文章列表请查看分类-Solidity. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文 ...