[Luogu 3224] HNOI2012 永无乡
[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 永无乡的更多相关文章
- 线段树合并+并查集 || BZOJ 2733: [HNOI2012]永无乡 || Luogu P3224 [HNOI2012]永无乡
题面:P3224 [HNOI2012]永无乡 题解: 随便写写 代码: #include<cstdio> #include<cstring> #include<iostr ...
- 洛谷.3224.[HNOI2012]永无乡(Splay启发式合并)
题目链接 查找排名为k的数用平衡树 合并时用启发式合并,把size小的树上的所有节点插入到size大的树中,每个节点最多需要O(logn)时间 并查集维护连通关系即可 O(nlogn*insert t ...
- BZOJ 2733: [HNOI2012]永无乡 启发式合并treap
2733: [HNOI2012]永无乡 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...
- bzoj 2733: [HNOI2012]永无乡 离线+主席树
2733: [HNOI2012]永无乡 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1167 Solved: 607[Submit][Status ...
- BZOJ 2733: [HNOI2012]永无乡(treap + 启发式合并 + 并查集)
不难...treap + 启发式合并 + 并查集 搞搞就行了 --------------------------------------------------------------------- ...
- BZOJ 2733: [HNOI2012]永无乡 [splay启发式合并]
2733: [HNOI2012]永无乡 题意:加边,询问一个连通块中k小值 终于写了一下splay启发式合并 本题直接splay上一个节点对应图上一个点就可以了 并查集维护连通性 合并的时候,把siz ...
- B20J_2733_[HNOI2012]永无乡_权值线段树合并
B20J_2733_[HNOI2012]永无乡_权值线段树合并 Description:n座岛,编号从1到n,每座岛都有自己的独一无二的重要度,按照重要度可以将这n座岛排名,名次用1到 n来表示.某些 ...
- bzoj2733: [HNOI2012]永无乡 启发式合并
地址:http://www.lydsy.com/JudgeOnline/problem.php?id=2733 题目: 2733: [HNOI2012]永无乡 Time Limit: 10 Sec ...
- [HNOI2012]永无乡 线段树合并
[HNOI2012]永无乡 LG传送门 线段树合并练手题,写这篇博客只是为了给我的这篇文章找个板子题. 并查集维护连通性,对于不在同一个连通块内的合并操作每次直接合并两颗线段树,复杂度\(O(n \l ...
随机推荐
- Appium基础环境搭建(windows)---基于python
1 JDK安装 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 安装注意:安装 ...
- Thunder团队第三周 - Scrum会议1
Scrum会议1 小组名称:Thunder 项目名称:i阅app Scrum Master:王航 工作照片: 杨梓瑞在拍照,所以不在照片中. 参会成员: 王航(Master):http://www.c ...
- NSTimer使用注意事项
1.scheduled开头和非schedule的开头方法的区别.系统框架提供了几种创建NSTimer的方法,其中以scheduled开头的方法会自动把timer加入当前run loop,到了设定的时间 ...
- <Effective C++>读书摘要--Inheritance and Object-Oriented Design<二>
<Item 36> Never redefine an inherited non-virtual function 1.如下代码通过不同指针调用同一个对象的同一个函数会产生不同的行为Th ...
- sublime text 3103 怎么设置中文
1.shift+ctrl+p调出插件管理,输入install package,按enter键,开始安装. 2.搜索chinese即可,下载安装插件包即可 原文:http://blog.csdn.net ...
- TreeView的使用
用于显示多级层次关系 每一项是一个节点,也就是一个Node,是一个TreeNode节点,Nodes是该控件节点的集合. selectedNode用户选中的节点,如果没有选中则为null 1. 当选中后 ...
- tc:逼良为娼
tc的学习原来是想着直接从用户态学习的,但是万万没想到哇,qdisc class两个概念直接把我给搞晕了,直接看代码吧 调用:tc qdisc add dev tap0 root handle 1: ...
- 【codevs3160】最长公共子串 后缀数组
题目描述 给出两个由小写字母组成的字符串,求它们的最长公共子串的长度. 输入 读入两个字符串 输出 输出最长公共子串的长度 样例输入 yeshowmuchiloveyoumydearmotherrea ...
- [HAOI2010]计数 数位DP+组合数
题面: 你有一组非零数字(不一定唯一),你可以在其中插入任意个0,这样就可以产生无限个数.比如说给定{1,2},那么可以生成数字12,21,102,120,201,210,1002,1020,等等. ...
- POJ2406:Power Strings——题解
http://poj.org/problem?id=2406 就是给一个串,求其循环节的个数. 稍微想一下就知道,KMP中nxt数组记录了所有可与前面匹配的位置. 那么如果我们的循环节长度为k,有n个 ...