题目链接

查找排名为k的数用平衡树

合并时用启发式合并,把size小的树上的所有节点插入到size大的树中,每个节点最多需要O(logn)时间

并查集维护连通关系即可

O(nlogn*insert time)

据(主席)说按顺序插入能做到均摊O(1),中序遍历即可有序插入

1.并查集与平衡树是独立的!不要混用fa!并查集只起判断连通关系的作用

2.不需要记录root,Splay时到fa[x]=0即可,因为合并是在一棵树中插入

3.Splay中条件!

Update(18.10.2):Splay支持finger search,所以启发式合并是一个\(\log\)的。

Treap因为某种奇怪的性质所以启发式合并也是一个\(\log\)的。

set可能是。

#include<cstdio>
#include<cctype>
#include<algorithm>
#define gc() getchar()
const int N=1e5+5; int n,m,ff[N],t[N],son[N][2],fa[N],sz[N]; inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
} inline void Update(int rt)
{
sz[rt]=sz[son[rt][0]]+sz[son[rt][1]]+1;
}
void Rotate(int x)
{
int a=fa[x],b=fa[a],l=son[a][1]==x,r=l^1;
if(b) son[b][son[b][1]==a]=x;
// if(!a) printf("Warning:b:%d x:%d\n",b,x);
fa[x]=b, fa[a]=x, fa[son[x][r]]=a;
son[a][l]=son[x][r], son[x][r]=a;
Update(a), Update(x);
}
void Splay(int x)
{
while(fa[x])//相差不大,反而这样略快
{
int a=fa[x],b=fa[a];
if(b)//注意是fa[a]!
{//如果是a,那若这时fa[a]=0,fa[x]会变为0,再经一次Rotate(x)后会改变fa[x]即fa[0]的值
if((son[a][1]==x)^(son[b][1]==a)) Rotate(x);
else Rotate(a);
}
Rotate(x);
}
// for(int f;f=fa[x];Rotate(x))
// if(fa[f])
// ((son[f][1]==x)^(son[fa[f]][1]==f))?Rotate(x):Rotate(f);
}
void Insert(int k,int y)
{
while(son[k][t[y]>t[k]]) k=son[k][t[y]>t[k]];
fa[y]=k, son[k][t[y]>t[k]]=y, sz[y]=1;
++sz[k];
// printf("k:%d fa:%d\n",k,fa[k]);
Splay(k);
}
int Getf(int x)
{
return x==ff[x]?x:ff[x]=Getf(ff[x]);
}
void DFS(int tar,int y)
{
int l=son[y][0],r=son[y][1];//要清空节点信息,所以清空前要记录
son[y][0]=son[y][1]=fa[y]=/*sz[y]=*/0;
if(l) DFS(tar,l);
Insert(tar,y);
if(r) DFS(tar,r);
}
void Merge(int x,int y)
{
// int r1=Getf(x),r2=Getf(y);
if(x==y) return;
Splay(x),Splay(y);//保证复杂度
if(sz[x]<sz[y]) std::swap(x,y);
ff[y]=x;
DFS(x,y);
}
int Rank(int v,int x)
{
Splay(x);
if(v>sz[x]) return -1;
int k=x;
while(1)
{
if(sz[son[k][0]]+1>=v && sz[son[k][0]]<v) return k;
if(sz[son[k][0]]>=v) k=son[k][0];
else v-=sz[son[k][0]]+1,k=son[k][1];
}
} int main()
{
#ifndef ONLINE_JUDGE
freopen("3224.in","r",stdin);
#endif n=read(),m=read();
for(int i=1;i<=n;++i) t[i]=read(),ff[i]=i,sz[i]=1;
int q,a,b;
char s[5];
while(m--) a=Getf(read()),b=Getf(read()),Merge(a,b);
q=read();
while(q--)
{
scanf("%s",s),a=Getf(read()),b=read();
if(s[0]=='Q') printf("%d\n",Rank(b,a));
else b=Getf(b),Merge(a,b);
} return 0;
}

洛谷.3224.[HNOI2012]永无乡(Splay启发式合并)的更多相关文章

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

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

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

    题目: 洛谷3224 分析: 这题一看\(n\leq100000\)的范围就知道可以暴力地用\(O(nlogn)\)数据结构乱搞啊-- 每个联通块建一棵Splay树,查询就是Splay查询第k大的模板 ...

  3. 洛谷P3224 [HNOI2012]永无乡(线段树合并+并查集)

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

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

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

  5. 洛谷 P3224 [HNOI2012]永无乡 解题报告

    P3224 [HNOI2012]永无乡 题目描述 永无乡包含 \(n\) 座岛,编号从 \(1\) 到 \(n\) ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 \(n\) 座岛排名,名次用 ...

  6. 【BZOJ-2733】永无乡 Splay+启发式合并

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

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

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

  8. 洛谷 P3224 [HNOI2012]永无乡

    题面 永无乡包含 \(n\) 座岛,编号从 \(1\) 到 \(n\) ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 \(n\) 座岛排名,名次用 \(1\) 到 \(n\) 来表示.某些岛 ...

  9. 【bzoj2733】[HNOI2012]永无乡 Treap启发式合并

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

随机推荐

  1. 写好shell脚本的13个技巧【转】

    有多少次,你运行./script.sh,然后输出一些东西,但却不知道它刚刚都做了些什么.这是一种很糟糕的脚本用户体验.我将在这篇文章中介绍如何写出具有良好开发者体验的 shell 脚本. 产品的最终用 ...

  2. C# 清理消息管道的消息

    using System;using System.Collections.Generic;using System.Linq;using System.Messaging;using System. ...

  3. Asp.Net Core 快速邮件队列设计与实现

    发送邮件几乎是软件系统中必不可少的功能,在Asp.Net Core 中我们可以使用MailKit发送邮件,MailKit发送邮件比较简单,网上有许多可以参考的文章,但是应该注意附件名长度,和附件名不能 ...

  4. javaScript中自定义sort中的比较函数,用于比较字符串长度,数值大小

      , 1.2, 'bb', 'cc']; var len = arr.length; // for (var i = 0; i < len; i++) { // alert(arr + &qu ...

  5. 故障 -> nginx启动失败

    描述:在用saltstack给 minion 安装 nginx 服务 时 提示 nginx 服务下载成功,但是启动失败. ---------- ID: nginx-systemctl Function ...

  6. Android:ZoomControls控件

    ZoomControls控件 //_ZoomControls.java public class _ZoomControls extends Activity{ @Override protected ...

  7. xshell xftp免费版下载方法

    第一步:进入官网 https://www.netsarang.com/ 第二步:选中Free License 第三步:选中你要下的xftp或者xsell (l两个好像不能一块下,都要单独操作) 第四步 ...

  8. WPF设置对象隐藏、不可用

    设置隐藏时,这里将控件分为两类, 1.普通的按钮.下拉框等,根据控件的Name进行查找,设置IsEnabled为false; 2.ListView中嵌套控件,直接将列隐藏,根据GridViewColu ...

  9. ECLIPSE 导入外部文件或源码包

    步骤: 点击Project->Properties->Libraries->Add External Class Folder.. ->选择你的文件路径->确定 注:如果 ...

  10. 委托----Func和Action

    平时我们如果要用到委托一般都是先声明一个委托类型,比如: private delegate string Say(); string说明适用于这个委托的方法的返回类型是string类型,委托名Say后 ...