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 永 ...
随机推荐
- 180713-Spring之借助Redis设计访问计数器之扩展篇
之前写了一篇博文,简单的介绍了下如何利用Redis配合Spring搭建一个web的访问计数器,之前的内容比较初级,现在考虑对其进行扩展,新增访问者记录 记录当前站点的总访问人数(根据Ip或则设备号) ...
- Linux命令应用大词典-第21章 LVM和RAID管理
21.1 pvcreate:创建物理卷 21.2 pvscan:列出找到的物理卷 21.3 pvdisplay:显示物理卷的相关属性 21.4 vgcreate:创建卷组 21.5 vgscan:查找 ...
- JVM之G1收集器
Garbage-First,面向服务端的垃圾收集器. 并行与并发:充分利用多核环境减少停顿时间, 分代收集:不需要配合其它收集器 空间整合:整体上看属于标记整理算法,局部(region之间)数据复制算 ...
- [CodeForce431C]k-tree
Quite recently a creative student Lesha had a lecture on trees. After the lecture Lesha was inspired ...
- eclipse注释快捷键
1.单行注释 注释: ctrl + / 取消注释: ctrl + / 多行注释 注释: ctrl shift + / 取消注释: ctrl shift + \
- 【上传-下载】-jmeter工具
上 传 ================================================================================================ ...
- 1 wait notify
wait/notify: wait()使线程停止,notify使wait状态的线程继续执行. wait()是Object类的方法,该方法用来将线程置入“预执行队列”,并在wait()方法处停止执行,直 ...
- Thunder团队——事后诸葛亮会议
小组名称:Thunder 项目名称:爱阅APP 小组成员:王航 李传康 代秋彤 邹双黛 苗威 宋雨 胡佑蓉 杨梓瑞 一.设想和目标 1.我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型 ...
- vim编辑器配置及常用命令
最近工作不安分, 没有了刚入行时候的锐气, 不知道什么时候开始懈怠起来, 周末在电脑旁边看新闻, 搞笑图片, 追美剧, 一坐就是一天, 很是空虚. 我需要摆脱这种状态, 正好想学习一下安卓底层, An ...
- java集合类小结
1 集合的框架体系 List简介 集合的使用场合 List(链表|线性表)和Set(集) java.util.Collection ---| Collection 描述所有接口的共性 ----| Li ...