[Luogu 3224] HNOI2012 永无乡

<题目链接>


特别水一个平衡树题。

不认真的代价是调试时间指数增长。

我写的 SBT,因为 Treap 的 rand() 实在写够了。

用并查集维护这些点的关系,然后启发式暴力合并,以及找第 \(k\) 小。

就是把子树较小的并到较大的里,一个一个点插入。

因为要插入新的点,给 SBT 预留的空间要大一些。(我试过只改变原来的点的信息,结果失败了。)

SBT 需要开的空间为 \(MAXN+MAXM\),因为 \(n\) 个点,每个点最多被插入 \(m\) 次。

就这样。

表白一万次 SBT 的 Maintain 操作代码,超优美的qwq。

#include <algorithm>
#include <cstdio>
#include <cstring>
using std::swap;
const int MAXN=100010,MAXM=400010;
int n,m,q;
class UFS
{
public:
void Init(int i)
{
f[i]=i;
}
int Find(int x)
{
return x==f[x] ? f[x] : f[x]=Find(f[x]);
}
void Merge(int x,int y)
{
f[Find(y)]=Find(x);
}
private:
int f[MAXN];
}S;
class SBT
{
public:
SBT(int cnt=0):cnt(cnt){}
void Init(void)
{
for(int i=1,x;i<=n;++i)
{
scanf("%d",&x);
S.Init(i),s[rt[i]=++cnt]=node(x,i,1);
}
}
void Bridge(int x,int y)
{
int a=S.Find(x),b=S.Find(y);
if(a==b)
return;
if(s[rt[a]].size>s[rt[b]].size)
S.Merge(a,b),Merge(rt[a],b);
else
S.Merge(b,a),Merge(rt[b],a);
}
int FindKth(int x,int k)
{
return k>s[x=rt[S.Find(x)]].size ? -1 : Find(x,k);
}
private:
int cnt,rt[MAXN];
struct node
{
int v,num,size,c[2];
node(int v=0,int num=0,int size=0):v(v),num(num),size(size)
{
memset(c,0,sizeof c);
}
}s[MAXM];
void Update(int i)
{
s[i].size=s[s[i].c[0]].size+s[s[i].c[1]].size+1;
}
void Rotate(int &i,bool p)
{
int t=s[i].c[!p];
s[i].c[!p]=s[t].c[p],s[t].c[p]=i;
Update(i),Update(i=t);
}
void Maintain(int &i,bool p)
{
int t=s[s[i].c[!p]].size;
if(t<s[s[s[i].c[p]].c[p]].size)
Rotate(i,!p);
else if(t<s[s[s[i].c[p]].c[!p]].size)
Rotate(s[i].c[p],p),Rotate(i,!p);
else
return;
Maintain(s[i].c[0],0),Maintain(s[i].c[1],1),Maintain(i,0),Maintain(i,1);
}
void Insert(int &i,int x,int num)
{
if(!i)
{
s[i=++cnt]=node(x,num,1);
return;
}
++s[i].size;
bool t=x>s[i].v;
Insert(s[i].c[t],x,num);
Maintain(i,t);
}
void Merge(int &x,int &y)
{
if(!y)
return;
Insert(x,s[y].v,s[y].num),Merge(x,s[y].c[0]),Merge(x,s[y].c[1]);
}
int Find(int i,int x)
{
int t;
while(x!=(t=s[s[i].c[0]].size+1))
if(x<t)
i=s[i].c[0];
else
x-=t,i=s[i].c[1];
return s[i].num;
}
}T;
int main(int argc,char *argv[])
{
scanf("%d %d",&n,&m);
T.Init();
for(int i=1,x,y;i<=m;++i)
{
scanf("%d %d",&x,&y);
T.Bridge(x,y);
}
scanf("%d",&q);
for(int i=1,x,y;i<=q;++i)
{
char c;
scanf("\n%c %d %d",&c,&x,&y);
if(c=='B')
T.Bridge(x,y);
else
printf("%d\n",T.FindKth(x,y));
}
return 0;
}

谢谢阅读。

[Luogu 3224] HNOI2012 永无乡的更多相关文章

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

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

  2. 洛谷.3224.[HNOI2012]永无乡(Splay启发式合并)

    题目链接 查找排名为k的数用平衡树 合并时用启发式合并,把size小的树上的所有节点插入到size大的树中,每个节点最多需要O(logn)时间 并查集维护连通关系即可 O(nlogn*insert t ...

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

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

  4. bzoj 2733: [HNOI2012]永无乡 离线+主席树

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1167  Solved: 607[Submit][Status ...

  5. BZOJ 2733: [HNOI2012]永无乡(treap + 启发式合并 + 并查集)

    不难...treap + 启发式合并 + 并查集 搞搞就行了 --------------------------------------------------------------------- ...

  6. BZOJ 2733: [HNOI2012]永无乡 [splay启发式合并]

    2733: [HNOI2012]永无乡 题意:加边,询问一个连通块中k小值 终于写了一下splay启发式合并 本题直接splay上一个节点对应图上一个点就可以了 并查集维护连通性 合并的时候,把siz ...

  7. B20J_2733_[HNOI2012]永无乡_权值线段树合并

    B20J_2733_[HNOI2012]永无乡_权值线段树合并 Description:n座岛,编号从1到n,每座岛都有自己的独一无二的重要度,按照重要度可以将这n座岛排名,名次用1到 n来表示.某些 ...

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

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

  9. [HNOI2012]永无乡 线段树合并

    [HNOI2012]永无乡 LG传送门 线段树合并练手题,写这篇博客只是为了给我的这篇文章找个板子题. 并查集维护连通性,对于不在同一个连通块内的合并操作每次直接合并两颗线段树,复杂度\(O(n \l ...

随机推荐

  1. windows远程连接失败问题排查思路

    一般情况下,对WIN7的远程连接只需要5步即可完成远程连接的设置: 1).用户是否设置了密码 2).计算机属性-允许远程登录 3).设置计算机永不睡眠 4).关闭防火墙或者设置入站规则 5).排查Re ...

  2. oracle数据库之PL/SQL 流程控制语句

    介绍 PL/SQL 的流程控制语句, 包括如下三类: 1.控制语句: IF 语句 2.循环语句: LOOP 语句, EXIT 语句 3.顺序语句: GOTO 语句, NULL 语句 一 条件语句 IF ...

  3. 浏览器中event.srcElement和event.target的兼容性问题

    在IE下,event对象有srcElement属性,但是没有target属性:Firefox下,even对象有target属性,但是没有srcElement属性.. 解决方法:使用obj(obj = ...

  4. python学习笔记01:安装python

    下载python: 从从https://www.python.org/downloads/下载python,根据操作系统的不同,选择不同的版本下载.注意:linux系统大多预装了python,可以直接 ...

  5. 用SC命令 添加或删除windows服务提示OpenSCManager 失败5 拒绝访问

    在安装命令行中安装  windowsOpenSCManager 失败5  的错误,原因是当前用户的权限不足,需要做的是在注册表 HKEY_LOCAL_MACHINE\Software\Microsof ...

  6. 使用协程(gevent)实现请求

    协程,又称微线程.英文名Coroutine. 协程最大的优势就是协程极高的执行效率.因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就 ...

  7. 用php实现一个双向队列 如何实现?

    PHP面试题作业 class DuiLie { private $array = array();//声明空数组 public function setFirst($item){ return arr ...

  8. table与div互相嵌套注意

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...

  9. springBoot配置分析(属性和结构化)

    使用idea自带插件创建项目 一直下一步到完成 application.properties local.ip.addr = 192.168.2.110 redis.host = 192.168.3. ...

  10. FLT_MIN,FLT_MAX,FLT_EPSILON

    FLT_MIN,FLT_MAX,FLT_EPSILON  * min positive value */最小的正值#define FLT_MIN 1.175494351e-38F /* max val ...