[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. Nodejs第一天-{Nodejs基础 深刻理解浏览器 环境变量 基础语法}

    Nodejs第一天 1.什么是Nodejs ​ Nodejs是一个可以运行(解析)ECMAScript的环境; ​ ECMAScript是规定了一些列的语法 ,这些语法想要解析的执行就需要放在某个环境 ...

  2. C中文件操作的文本模式和二进制模式,到底有啥区别?

    在C中,使用fopen打开文件有两种模式:一种是文本模式,一种是二进制模式.那这两种模式之间有什么区别,是不是使用文本模式打开的文件就只能使用文本函数比如fprintf来操作,而使用二进制打开的文件就 ...

  3. 第一课——从main到WinMain

    一.Visual C++6.0 由微软公司推出的基于Windows系统的可视化集成开发环境(IDE) 微软公司为其开发了功能强大的MFC(Microsoft Foundation Class,微软基础 ...

  4. LintCode-371.用递归打印数字

    用递归打印数字 用递归的方法找到从1到最大的N位整数. 注意事项 用下面这种方式去递归其实很容易: recursion(i) { if i > largest number: return re ...

  5. <Effective C++>读书摘要--Resource Management<一>

    1.除了内存资源以外,Other common resources include file descriptors, mutex locks, fonts and brushes in graphi ...

  6. #Leetcode# 700. Search in a Binary Search Tree

    https://leetcode.com/problems/search-in-a-binary-search-tree/ Given the root node of a binary search ...

  7. 把jar包加入本地maven库内

    1首先,在项目的pom.xml文件中加入 <dependency><groupId>taobao-alidayu</groupId>  //名字随便取不要跟已有的重 ...

  8. 相机上的P,S,A,M分别是什么单词的缩写?

    程序曝光 Programmed Auto快门优先 Shutter Priority光圈优先 aperture-priority 全手动模式 Manual Mode

  9. 【Docker 命令】- ps命令

    docker ps : 列出容器 语法 docker ps [OPTIONS] OPTIONS说明: -a:显示所有的容器,包括未运行的. -f:根据条件过滤显示的内容. --format :指定返回 ...

  10. 伟大的淘宝IP库的API接口竟然提示503挂掉了

    1 淘宝IP库惊现503错误 吃完晚饭,大概6点半了,天色已暗,太阳早就落山了.回到宿舍打开博客一看,傻眼了:博客每篇文章的评论者的地理信息全部处于“正在查询中……”的状态.这神马情况,不会是被淘宝封 ...