题目链接

查找排名为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. caffe-win10-cifar10

    因为是在win10下安装的GPU版caffe,所以不能直接运行linux里的shell脚本.但是win10自带bash,可以运行.sh文件,网上也有直接下Cygwin和git的.我是下载好git后才知 ...

  2. 高级 Java 面试通关知识点整理!

    1.常用设计模式 单例模式:懒汉式.饿汉式.双重校验锁.静态加载,内部类加载.枚举类加载.保证一个类仅有一个实例,并提供一个访问它的全局访问点. 代理模式:动态代理和静态代理,什么时候使用动态代理. ...

  3. robotium之无name、ID仅有desc定位

    场景如图: 没有name和ID,群里问了,也没人搭理我,自己试验了下,发现这个法子可用,直接贴代码: Activity act = solo.getCurrentActivity(); int ide ...

  4. 如何查看centos系统cpu/内存使用情况

    1.查看硬盘 [mushme@investide ~]$ df -ah 文件系统              容量  已用 可用 已用% 挂载点 /dev/cciss/c0d0p1     123G   ...

  5. VeeValidate配置中文的两种方法

    使用VeeValidate时遇到的问题,下面是我找到的一些解决办法: VeeValidate一直报错早不到addlocale方法 解决办法:1.卸载掉当前版本,重新安装低版本如2.0.0-rc.25  ...

  6. java多线程快速入门(九)

    多线程安全问题(卖火车票案例) package com.cppdy; class MyThread5 implements Runnable{ private Integer ticketCount= ...

  7. 使用exundelete在Linux下恢复删除的文件

    原文:https://my.oschina.net/looly/blog/261912 Linux下执行 rm 并不会真正删除,而是将inode节点中的扇区删除,同时释放数据块.在数据块被系统重新分配 ...

  8. html----属性操作

    1.文本 十六进制值 - 如: #FF0000 一个RGB值 - 如: RGB(255,0,0) 颜色的名称 - 如:  red‘’RGBA() 2.水平对齐方式 text-align 属性规定元素中 ...

  9. uva11610 树状数组+素数打表求因子,好题!

    /* uva11610 树状数组+素数打表+离散化 打出的素数范围在2-1000000之间,不超过六位数,然后按照格式翻转成七位数 */ #include<bits/stdc++.h> u ...

  10. C#泛型(一)

    简介: 先看看泛型的概念--“通过参数化类型来实现在同一份代码上操作多种数据类型.利用“参数化类型”将类型抽象化,从而实现灵活的复用”. 很多初学者在刚开始接触泛型的时候会比较难理解 “泛型” 在这里 ...