这题之前写过线段树合并,今天复习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+启发式合并/线段树合并)的更多相关文章

  1. BZOJ2733 [HNOI2012]永无乡(并查集+线段树合并)

    题目大意: 在$n$个带权点上维护两个操作: 1)在点$u,v$间连一条边: 2)询问点$u$所在联通块中权值第$k$小的点的编号,若该联通块中的点的数目小于$k$,则输出$-1$: 传送门 上周的模 ...

  2. B20J_2733_[HNOI2012]永无乡_权值线段树合并

    B20J_2733_[HNOI2012]永无乡_权值线段树合并 Description:n座岛,编号从1到n,每座岛都有自己的独一无二的重要度,按照重要度可以将这n座岛排名,名次用1到 n来表示.某些 ...

  3. [BZOJ2733] [HNOI2012] 永无乡 (splay启发式合并)

    Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以 ...

  4. [bzoj2733][HNOI2012]永无乡_权值线段树_线段树合并

    永无乡 bzoj-2733 HNOI-2012 题目大意:题目链接. 注释:略. 想法: 它的查询操作非常友善,就是一个联通块内的$k$小值. 故此我们可以考虑每个联通块建一棵权值线段树. 这样的话每 ...

  5. 【BZOJ-2733】永无乡 Splay+启发式合并

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2048  Solved: 1078[Submit][Statu ...

  6. BZOJ 2733: [HNOI2012]永无乡 [splay启发式合并]

    2733: [HNOI2012]永无乡 题意:加边,询问一个连通块中k小值 终于写了一下splay启发式合并 本题直接splay上一个节点对应图上一个点就可以了 并查集维护连通性 合并的时候,把siz ...

  7. 【洛谷3224/BZOJ2733】[HNOI2012]永无乡 (Splay启发式合并)

    题目: 洛谷3224 分析: 这题一看\(n\leq100000\)的范围就知道可以暴力地用\(O(nlogn)\)数据结构乱搞啊-- 每个联通块建一棵Splay树,查询就是Splay查询第k大的模板 ...

  8. 洛谷.3224.[HNOI2012]永无乡(Splay启发式合并)

    题目链接 查找排名为k的数用平衡树 合并时用启发式合并,把size小的树上的所有节点插入到size大的树中,每个节点最多需要O(logn)时间 并查集维护连通关系即可 O(nlogn*insert t ...

  9. bzoj2733: [HNOI2012]永无乡 启发式合并

    地址:http://www.lydsy.com/JudgeOnline/problem.php?id=2733 题目: 2733: [HNOI2012]永无乡 Time Limit: 10 Sec   ...

  10. bzoj2733: [HNOI2012]永无乡(splay)

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3778  Solved: 2020 Description 永 ...

随机推荐

  1. 「日常训练」Alternative Thinking(Codeforces Round #334 Div.2 C)

    题意与分析 (CodeForces - 603A) 这题真的做的我头疼的不得了,各种构造样例去分析性质... 题意是这样的:给出01字符串.可以在这个字符串中选择一个起点和一个终点使得这个连续区间内所 ...

  2. 第二篇 Flask基础篇之(闪现,蓝图,请求扩展,中间件)

    本篇主要内容: 闪现 请求扩展 中间件 蓝图 写装饰器,常用 functools模块,帮助设置函数的元信息 import functools def wrapper(func): @functools ...

  3. Objective-C 内存管理和ARC

    内存管理 范围: 任何继承了NSObject的对象 对基本数据类型无效 原理: 每个对象内部都保存了一个与之相关联的整数 称为引用计数器 1.计数器的基本操作 当使用alloc new或者copy创建 ...

  4. Pyhton网络爬虫实例_豆瓣电影排行榜_Xpath方法爬取

    -----------------------------------------------------------学无止境------------------------------------- ...

  5. 微信小程序 选项 、时间日期选择器

    wxml: <view class="section" > <picker bindchange="bindPickerChange" val ...

  6. spark dataset join 使用方法java

    dataset<Row> df1,df2,df3 //该方法可以执行成功 df3= df1.join(df2,"post_id").selectExpr("h ...

  7. 随机森林random forest及python实现

    引言想通过随机森林来获取数据的主要特征 1.理论根据个体学习器的生成方式,目前的集成学习方法大致可分为两大类,即个体学习器之间存在强依赖关系,必须串行生成的序列化方法,以及个体学习器间不存在强依赖关系 ...

  8. Halcon10 下载

    Halcon10 下载地址:http://www.211xun.com/download_page_1.html HALCON 10 是一套机器视觉图像处理库,由一千多个算子以及底层的数据管理核心构成 ...

  9. 统计学习五:3.决策树的学习之CART算法

    全文引用自<统计学习方法>(李航) 分类与回归树(classification and regression tree, CART)模型是由Breiman等人于1984年提出的另一类决策树 ...

  10. JAVA集合类(大公司面试喜欢问的)

     分类: 核心JAVA(11)  版权声明:本文为博主原创文章,未经博主允许不得转载. 看了一些所谓大公司的Java面试问题,发现对于JAVA集合类的使用都比较看重似的,而自己在这方面还真的是所真甚少 ...