题目链接

查找排名为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. python日志和异常

    “日志”转载:http://www.cnblogs.com/dkblog/archive/2011/08/26/2155018.html "异常"转载:http://www.cnb ...

  2. springboot系列十三、springboot集成swaggerUI

    一.Swagger介绍 Swagger能成为最受欢迎的REST APIs文档生成工具之一,有以下几个原因: Swagger 可以生成一个具有互动性的API控制台,开发者可以用来快速学习和尝试API. ...

  3. oracle数据库自增主键重复

    select max(t.id) from T_PLAT_ENUM_VALUE tdrop sequence T_PLAT_ENUM_VALUE;create sequence T_PLAT_ENUM ...

  4. C++:explicit关键字

    在C++中,如果一个类的构造函数只有一个形参,在这种情况下,可以直接将一个对应于构造函数参数类型的数据直接赋值给类变量,编译器在编译时会自动进行类型转换,将对应于构造函数参数类型的数据转换为类的对象, ...

  5. oracle flashback 后主键及索引更改问题

    oracle flashback 后 主键会变为bin开头,如果删除可以采用将sql复制出单独窗口,然后加上“”执行

  6. spring+activemq配置文件内容及实现原理

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  7. 通达OA批量处理没有结束但前台显示已经结束的流程

    问题描述: 通达OA系统出现大量流程没有结束,系统显示结束的问题 通过查询操作系统日志,数据库日志,包括程序日志没有发现异常,通过观察发现大量的流程结束时间都是在2016-02-16 17:32:XX ...

  8. js 将图片连接转换称base64格式

    我们把图像文件的内容直接写在了HTML 文件中,这样做的好处是,节省了一个HTTP 请求.坏处呢,就是浏览器不会缓存这种图像.现在我们提供一个js: function convertImgToBase ...

  9. cas中总是得不到返回的属性

    cas可以登录,但是得不到返回的属性,后来看日志才知道数据库链接报错,原来URL中少了jdbc:.真是愚蠢的错误,记录之,警之!

  10. LeetCode(64):最小路径和

    Medium! 题目描述: 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小. 说明:每次只能向下或者向右移动一步. 示例: 输入: [   [1 ...