bzoj2733: [HNOI2012]永无乡(splay+启发式合并/线段树合并)
这题之前写过线段树合并,今天复习Splay的时候想起这题,打算写一次Splay+启发式合并。
好爽!!!
写了长长的代码(其实也不长),只凭着下午的一点记忆(没背板子。。。),调了好久好久,过了样例,submit,1A!
哇真的舒服
调试输出懒得删了QwQ
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
#define ll long long
#define which(x) (son[fq[x]][1]==x)
using namespace std;
const int maxn=,extar[]={-,};
int n,m,x,y,z,tot,q,cnt;
int fa[maxn],data[maxn],size[maxn],a[maxn],son[maxn][],fq[maxn],id[maxn],root[maxn];
char ch[maxn];
void read(int &k)
{
int f=;k=;char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(c<=''&&c>='')k=k*+c-'',c=getchar();
k*=f;
}
int gf(int x){return fa[x]==x?x:fa[x]=gf(fa[x]);}
int search(int x,int k)
{
//printf("KPM%d %d %d\n",x,k,son[x][1]);
if(data[x]<k&&son[x][])return search(son[x][],k);
if(data[x]>k&&son[x][])return search(son[x][],k);
return x;
}
void rotate(int x)
{
int f=fq[x];bool k=which(x);
son[f][k]=son[x][!k];
son[x][!k]=f;
son[fq[f]][which(f)]=x;
fq[x]=fq[f];
fq[f]=x;
if(son[f][k])fq[son[f][k]]=f;
size[x]=size[f];
size[f]=size[son[f][]]+size[son[f][]]+;
//printf("%d %d %d ORZCZL\n",x,f,size[x]);
}
void splay(int x)
{
while(fq[x])
{
int f=fq[x];
if(!fq[f])
{
rotate(x);
break;
}
if(which(x)^which(f))rotate(x);
else rotate(f);
rotate(x);
}
}
void insert(int &x,int w)
{
//printf("%d %d\n",x,w);
if(!x){x=++tot;data[tot]=a[w];size[tot]=;id[x]=w;return;}
int k=search(x,a[w]);
//printf("qiguai%d %d %d\n",k,a[w],data[k]);
//printf("QAQ");
++tot;
data[tot]=a[w];fq[tot]=k;id[tot]=w;
if(a[w]<data[k])son[k][]=tot;
else son[k][]=tot;
size[tot]=;
while(k)size[k]++,k=fq[k];
splay(tot);
x=tot;
}
int rank(int x,int k)
{
//++cnt;
//printf("%d %d %d\n",x,k,size[son[x][0]]);
//if(cnt>10)exit(0);
if(size[son[x][]]>=k)return rank(son[x][],k);
if((size[son[x][]]+)==k)return x;
return rank(son[x][],k-size[son[x][]]-);
}
void merge(int x,int y)
{
//printf("WUWUWU%d %d\n",x,y);
if(son[x][])merge(son[x][],root[y]);
insert(root[y],id[x]);
if(son[x][])merge(son[x][],root[y]);
}
int main()
{
read(n);read(m);
for(int i=;i<=n;i++)
{
read(a[i]);
fa[i]=i;
}
//for(int i=1;i<=n;i++)printf("OAO%d\n",gf(i));
for(int i=;i<=m;i++)
{
read(x);read(y);
fa[gf(x)]=gf(y);
}
//for(int i=1;i<=n;i++)printf("QAQ%d %d\n",gf(i),root[gf(i)]);
//printf("\n");
for(int i=;i<=n;i++)insert(root[gf(i)],i);
//for(int i=1;i<=n;i++)printf("QAQ%d %d\n",gf(i),root[gf(i)]);
//printf("%dQQQQQQQQQQQQQQ\n",son[root[gf(1)]][0]);
read(q);
for(int i=;i<=q;i++)
{
scanf("%s",ch);read(x);read(y);
if(ch[]=='Q')
{
x=gf(x);
//printf("%d %d\n",root[x],size[root[x]]);
if(size[root[x]]<y)printf("-1\n");
else
{
int pos=rank(root[x],y);
printf("%d\n",id[pos]),splay(pos),root[x]=pos;
}
}
else
{
x=gf(x);y=gf(y);
if(x!=y)
{
//printf("%d %d %d %d\n",root[x],root[y],size[root[x]],size[root[y]]);
if(size[root[x]]>size[root[y]])swap(x,y);
fa[x]=y;
merge(root[x],y);
root[x]=;
}
}
}
return ;
}
UPD:改了下insert
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
#define ll long long
#define which(x) (son[fq[x]][1]==x)
using namespace std;
const int maxn=,extar[]={-,};
int n,m,x,y,z,tot,q,cnt;
int fa[maxn],data[maxn],size[maxn],a[maxn],son[maxn][],fq[maxn],id[maxn],root[maxn];
char ch[maxn];
void read(int &k)
{
int f=;k=;char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(c<=''&&c>='')k=k*+c-'',c=getchar();
k*=f;
}
int gf(int x){return fa[x]==x?x:fa[x]=gf(fa[x]);}
int search(int x,int k)
{
if(data[x]<k&&son[x][])return search(son[x][],k);
if(data[x]>k&&son[x][])return search(son[x][],k);
return x;
}
void rotate(int x)
{
int f=fq[x];bool k=which(x);
son[f][k]=son[x][!k];
son[x][!k]=f;
son[fq[f]][which(f)]=x;
fq[x]=fq[f];
fq[f]=x;
if(son[f][k])fq[son[f][k]]=f;
size[x]=size[f];
size[f]=size[son[f][]]+size[son[f][]]+;
}
void splay(int x)
{
while(fq[x])
{
int f=fq[x];
if(!fq[f])
{
rotate(x);
break;
}
if(which(x)^which(f))rotate(x);
else rotate(f);
rotate(x);
}
}
void insert(int &x,int w,int f)
{
if(!x)
{
x=++tot;
data[x]=a[w];
size[x]=;
id[x]=w;
fq[x]=f;
return;
}
if(a[w]<data[x])insert(son[x][],w,x);
else insert(son[x][],w,x);
size[x]++;
}
int rank(int x,int k)
{
if(size[son[x][]]>=k)return rank(son[x][],k);
if((size[son[x][]]+)==k)return x;
return rank(son[x][],k-size[son[x][]]-);
}
void merge(int x,int y)
{
if(son[x][])merge(son[x][],root[y]);
insert(root[y],id[x],);splay(tot);root[y]=tot;
if(son[x][])merge(son[x][],root[y]);
}
int main()
{
read(n);read(m);
for(int i=;i<=n;i++)
{
read(a[i]);
fa[i]=i;
}
for(int i=;i<=m;i++)
{
read(x);read(y);
fa[gf(x)]=gf(y);
}
for(int i=;i<=n;i++)insert(root[gf(i)],i,),splay(tot),root[gf(i)]=tot;
read(q);
for(int i=;i<=q;i++)
{
scanf("%s",ch);read(x);read(y);
if(ch[]=='Q')
{
x=gf(x);
if(size[root[x]]<y)printf("-1\n");
else
{
int pos=rank(root[x],y);
printf("%d\n",id[pos]),splay(pos),root[x]=pos;
}
}
else
{
x=gf(x);y=gf(y);
if(x!=y)
{
if(size[root[x]]>size[root[y]])swap(x,y);
fa[x]=y;
merge(root[x],y);
root[x]=;
}
}
}
return ;
}
bzoj2733: [HNOI2012]永无乡(splay+启发式合并/线段树合并)的更多相关文章
- BZOJ2733 [HNOI2012]永无乡(并查集+线段树合并)
题目大意: 在$n$个带权点上维护两个操作: 1)在点$u,v$间连一条边: 2)询问点$u$所在联通块中权值第$k$小的点的编号,若该联通块中的点的数目小于$k$,则输出$-1$: 传送门 上周的模 ...
- B20J_2733_[HNOI2012]永无乡_权值线段树合并
B20J_2733_[HNOI2012]永无乡_权值线段树合并 Description:n座岛,编号从1到n,每座岛都有自己的独一无二的重要度,按照重要度可以将这n座岛排名,名次用1到 n来表示.某些 ...
- [BZOJ2733] [HNOI2012] 永无乡 (splay启发式合并)
Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以 ...
- [bzoj2733][HNOI2012]永无乡_权值线段树_线段树合并
永无乡 bzoj-2733 HNOI-2012 题目大意:题目链接. 注释:略. 想法: 它的查询操作非常友善,就是一个联通块内的$k$小值. 故此我们可以考虑每个联通块建一棵权值线段树. 这样的话每 ...
- 【BZOJ-2733】永无乡 Splay+启发式合并
2733: [HNOI2012]永无乡 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2048 Solved: 1078[Submit][Statu ...
- BZOJ 2733: [HNOI2012]永无乡 [splay启发式合并]
2733: [HNOI2012]永无乡 题意:加边,询问一个连通块中k小值 终于写了一下splay启发式合并 本题直接splay上一个节点对应图上一个点就可以了 并查集维护连通性 合并的时候,把siz ...
- 【洛谷3224/BZOJ2733】[HNOI2012]永无乡 (Splay启发式合并)
题目: 洛谷3224 分析: 这题一看\(n\leq100000\)的范围就知道可以暴力地用\(O(nlogn)\)数据结构乱搞啊-- 每个联通块建一棵Splay树,查询就是Splay查询第k大的模板 ...
- 洛谷.3224.[HNOI2012]永无乡(Splay启发式合并)
题目链接 查找排名为k的数用平衡树 合并时用启发式合并,把size小的树上的所有节点插入到size大的树中,每个节点最多需要O(logn)时间 并查集维护连通关系即可 O(nlogn*insert t ...
- bzoj2733: [HNOI2012]永无乡 启发式合并
地址:http://www.lydsy.com/JudgeOnline/problem.php?id=2733 题目: 2733: [HNOI2012]永无乡 Time Limit: 10 Sec ...
- bzoj2733: [HNOI2012]永无乡(splay)
2733: [HNOI2012]永无乡 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3778 Solved: 2020 Description 永 ...
随机推荐
- Python汉诺塔问题递归算法与程序
汉诺塔问题: 问题来源:汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从上往下从小到大顺序摞着64片黄金圆盘.上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱 ...
- Python类对象
python类对象 python类对象支持两种操作:属性引用和实例化. 属性引用 使用 Python 中所有属性引用所使用的标准语法: obj.name. 有效的属性名称是类对象被创建时存在于类命名空 ...
- Python教程:Python中的for 语句
Python 中的 for 语句与你在 C 或 Pascal 中可能用到的有所不同. Python教程 中的 for 语句并不总是对算术递增的数值进行迭代(如同 Pascal),或是给予用户定义迭代步 ...
- 树的层次遍历(Trees on the level,UVA 122)
题目描述: 题目思路: 1.用结构链表来建树 2.用队列来实现层次遍历,当遍历到根节点时,将其子节点压入队列 #include <iostream> #include <cstdli ...
- JDK源码分析:Integer.java部分源码解析
1)声明部: public final class Integer extends Number implements Comparable<Integer> extends Number ...
- 使用Python客户端(redis-py)连接Redis--华为云DCS for Redis使用经验
使用Python连接Redis,需要先安装Python以及redis-py,以CentOS为例,介绍redis-py的客户端环境搭建. 第0步:准备工作 华为云上购买1台弹性云服务器ECS(我选了Ce ...
- poj 3468 (区间修改 区间查询)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions:147133 ...
- 词嵌入向量WordEmbedding
词嵌入向量WordEmbedding的原理和生成方法 WordEmbedding 词嵌入向量(WordEmbedding)是NLP里面一个重要的概念,我们可以利用WordEmbedding将一个单 ...
- 【转载】android 常用开源框架
对于Android初学者以及对于我们菜鸟,这些大神们开发的轻量级框架非常有用(更别说开源的了). 下面转载这10个框架的介绍:(按顺序来吧没有什么排名). 一. Afinal 官方介绍: Afina ...
- Python字符串中的r前缀
在Python中,如果字符串的前面有r/R前缀,那么,就会禁用转义符\的功能: >>>path = r'C:\new\text.dat' >>>pah 'C:\\n ...