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 永 ...
随机推荐
- OSG-更新和回调
本文转至http://www.cnblogs.com/shapherd/archive/2010/08/10/osg.html 作者写的比较好,再次收藏,希望更多的人可以看到这个文章 互联网是是一个相 ...
- MySQL☞abs函数
abs( )函数:求出绝对值 格式: select abs(数值) from 表名 如下图:
- 树的层次遍历(Trees on the level,UVA 122)
题目描述: 题目思路: 1.用结构链表来建树 2.用队列来实现层次遍历,当遍历到根节点时,将其子节点压入队列 #include <iostream> #include <cstdli ...
- chrome编辑器与截图
在地址栏中输入 data:text/html,<html contenteditable>即可使用编辑功能,打开控制台,ctrl + shift + p 调用命令面板,输入 capture ...
- appium 元素定位与操作:
一.常用识别元素的工具 uiautomator:Android SDK自带的一个工具,在tools目录下 monitor:Android SDK自带的一个工具,在tools目录下 Appium I ...
- Dev c++ 调试步骤
不能调试的时候,修改下列地方: 1.在“工具”->编译选项->”Add following commands when calling complier”下面的编辑框里写入:-g3 2.在 ...
- html5 canvas绘制环形进度条,环形渐变色仪表图
html5 canvas绘制环形进度条,环形渐变色仪表图 在绘制圆环前,我们需要知道canvas arc() 方 ...
- Thunder团队Beta周贡献分规则
小组名称:Thunder 项目名称:i阅app 组长:王航 成员:李传康.翟宇豪.邹双黛.苗威.宋雨.胡佑蓉.杨梓瑞 分配规则 规则1:基础分,拿出总分的20%(8分)进行均分,剩下的80%(32分) ...
- Thunder团队第三周 - Scrum会议5
Scrum会议5 小组名称:Thunder 项目名称:i阅app Scrum Master:苗威 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李传康 ...
- matlab 直方图均衡化(含rgb)
步骤: 统计原图像素每个像素的个数 统计原图像<每个灰度级的像素的累积个数 家里灰度级得映射规则 将原图每个像素点的灰度映射到新图 代码: clear all I=imread('1.jpg') ...