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 永 ...
随机推荐
- 「日常训练&知识学习」单调栈
这几天的知识学习比较多,因为时间不够了.加油吧,为了梦想. 这里写几条简单的单调栈作为题解记录,因为单调栈的用法很简单,可是想到并转化成用这个需要一些题目的积淀. 相关博客参见:https://blo ...
- hdu2094产生冠军(思维题)
产生冠军 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- Linux命令应用大词典-第6章 文件处理
6.1 sort:对文件中的数据进行排序 6.2 uniq:将重复行从输出文件中删除 6.3 cut:从文件每行中输出选定的字节.字符或字段 6.4 comm:逐行比较两个已经排序的文件 6.5 di ...
- Python递归算法入门
递归是一种算法,它在编程里面有着广泛的应用: 1. 递归必须满足哪两个基本条件? 一.函数调用自身 二.设置了正确的返回条件 2. 思考一下,按照递归的特性,在编程中有没有不得不使用递归的情况? 答: ...
- TPO-14 C2 Prepare for a career in journalism
TPO-14 C2 Prepare for a career in journalism 第 1 段 1.Listen to a conversation between a student and ...
- 前端开发工程师 - 03.DOM编程艺术 - 期末考试
期末考试客观题 返回 倒计时: 01:24 1 单选(2分) 以下选项中不是节点类型的是 A. COMMENT_NODE B. DOCUMENT_NODE C. BODY_NODE D. E ...
- 关于maven项目中修改的JS不生效的解决方案
1. 问题描述 昨天下午博主在开发学习的过程中,碰到一个修改了JS无法生效的问题,折腾我不少的时间,现将百度到的解决方案总结一下,以便下次碰到类似问题能够最快的找到解决方案 2 解决方案 2.1 方案 ...
- es6笔记4^_^function
一.function默认参数 现在可以在定义函数的时候指定参数的默认值了,而不用像以前那样通过逻辑或操作符来达到目的了. es5 function sayHello(name){ //传统的指定默认参 ...
- CSP201509-2:日期计算
引言:CSP(http://www.cspro.org/lead/application/ccf/login.jsp)是由中国计算机学会(CCF)发起的"计算机职业资格认证"考试, ...
- block inline 和 inline-block
概念 block和inline这两个概念是简略的说法,完整确切的说应该是 block-level elements (块级元素) 和 inline elements (内联元素). block元素通常 ...