P3224 [HNOI2012]永无乡

题目描述

永无乡包含 \(n\) 座岛,编号从 \(1\) 到 \(n\) ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 \(n\) 座岛排名,名次用 \(1\) 到 \(n\) 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛到达另一个岛。如果从岛 \(a\) 出发经过若干座(含 \(0\) 座)桥可以 到达岛 \(b\) ,则称岛 \(a\) 和岛 \(b\) 是连通的。

现在有两种操作:

B x y 表示在岛 \(x\) 与岛 \(y\) 之间修建一座新桥。

Q x k 表示询问当前与岛 \(x\) 连通的所有岛中第 \(k\) 重要的是哪座岛,即所有与岛 \(x\) 连通的岛中重要度排名第 \(k\) 小的岛是哪座,请你输出那个岛的编号。

输入输出格式

输入格式:

第一行是用空格隔开的两个正整数 \(n\) 和 \(m\) ,分别表示岛的个数以及一开始存在的桥数。

接下来的一行是用空格隔开的 \(n\) 个数,依次描述从岛 \(1\) 到岛 \(n\) 的重要度排名。随后的 \(m\) 行每行是用空格隔开的两个正整数 \(a_i\)和 \(b_i\),表示一开始就存在一座连接岛 \(a_i\) 和岛 \(b_i\) 的桥。

后面剩下的部分描述操作,该部分的第一行是一个正整数 \(q\) ,表示一共有 \(q\) 个操作,接下来的 \(q\) 行依次描述每个操作,操作的 格式如上所述,以大写字母 \(Q\) 或 \(B\) 开始,后面跟两个不超过 \(n\) 的正整数,字母与数字以及两个数字之间用空格隔开。

输出格式:

对于每个 Q x k 操作都要依次输出一行,其中包含一个整数,表示所询问岛屿的编号。如果该岛屿不存在,则输出 \(−1\) 。

说明

对于 \(20\%\) 的数据 \(n \leq 1000, q \leq 1000\)

对于 \(100\%\) 的数据 \(n \leq 100000, m \leq n, q \leq 300000\)


题意:点有点权,维护连通块的第\(k\)值,支持加边操作

维护第\(k\)值可以使用主席树平衡树等,这里我使用主席树

加边额外并查集维护,合并直接启发式合并,查询直接查询即可

复杂度分析

设所有的块都被合并到一块去了,且每次合并两个块时它们的大小相等

则有式子

\(T(n)=2\times T(\frac{n}{2})+\frac{n}{2}log\frac{n}{2}\)

合并的复杂度是那个是因为一个有\(s\)大小的块的主席树的链的条数有\(s\)条

updata:又玩了玩复杂度,发现似乎最坏复杂度是这样,但不能这么简单的说明,我自己也不太清楚,当做大约是\(n\)个节点的合并的复杂度在\(O(n)-O(nlogm)\)左右的吧,如果有什么能说清楚复杂度的,烦请跟我说一声QAQ

总复杂度:\(O(nlog^2n)\)


Code:

#include <cstdio>
#include <algorithm>
const int N=1e5+10;
int a[N],b[N],num[N];
int root[N],ch[N*20][2],sum[N*20],tot,f[N],siz[N],n,m,q;
#define ls ch[now][0]
#define rs ch[now][1]
void updata(int now){sum[now]=sum[ls]+sum[rs];}
int build(int l,int r,int pos)
{
int now=++tot;
if(l==r)
{
sum[now]=1;
return now;
}
int mid=l+r>>1;
if(pos<=mid) ls=build(l,mid,pos);
else rs=build(mid+1,r,pos);
updata(now);
return now;
}
int Find(int x){return f[x]==x?x:Find(f[x]);}
#define ols ch[las][0]
#define ors ch[las][1]
void merge(int &now,int las,int l,int r)
{
if(!now) {now=las;return;}
if(l==r)
{
sum[now]+=sum[las];
return;
}
int mid=l+r>>1;
if(ols) merge(ls,ols,l,mid);
if(ors) merge(rs,ors,mid+1,r);
updata(now);
}
void swap(int &x,int &y){x+=y,y=-y,y+=x,x-=y;}
void Merge(int x,int y)
{
x=Find(x),y=Find(y);
if(x==y) return;
if(siz[x]<siz[y]) swap(x,y);
merge(root[x],root[y],1,n);
siz[x]+=siz[y];
f[y]=x;
}
int query(int now,int l,int r,int k)
{
if(sum[now]<k) return -1;
if(l==r) return num[l];
int mid=l+r>>1;
if(sum[ls]>=k) return query(ls,l,mid,k);
else return query(rs,mid+1,r,k-sum[ls]);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",a+i),b[i]=a[i];
std::sort(a+1,a+1+n);
for(int i=1;i<=n;i++)
b[i]=std::lower_bound(a+1,a+1+n,b[i])-a;
for(int i=1;i<=n;i++)
num[b[i]]=i,f[i]=i,siz[i]=1,root[i]=build(1,n,b[i]);
for(int u,v,i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
Merge(u,v);
}
scanf("%d",&q);
char op[5];
for(int u,v,i=1;i<=q;i++)
{
scanf("%s%d%d",op,&u,&v);
if(op[0]=='B') Merge(u,v);
else printf("%d\n",query(root[Find(u)],1,n,v));
}
return 0;
}

2018.9.3

洛谷 P3224 [HNOI2012]永无乡 解题报告的更多相关文章

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

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

  2. 洛谷 P3224 [HNOI2012]永无乡

    题面 永无乡包含 \(n\) 座岛,编号从 \(1\) 到 \(n\) ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 \(n\) 座岛排名,名次用 \(1\) 到 \(n\) 来表示.某些岛 ...

  3. [洛谷P3224][HNOI2012]永无乡

    题目大意:给你$n$个点,每个点有权值$k$,现有两种操作: 1. $B\;x\;y:$将$x,y$所在联通块合并2. $Q\;x\;k:$查询第$x$个点所在联通块权值第$k$小是哪个数 题解:线段 ...

  4. 2018.08.11 洛谷P3224 [HNOI2012]永无乡(线段树合并)

    传送门 给出n个带点权的点,支持连边和查询连通块第k大. 这个貌似就是一道线段树合并的裸板啊... 代码: #include<bits/stdc++.h> #define N 100005 ...

  5. [HNOI2012] 永无乡 解题报告 (splay+启发式合并)

    题目链接:https://www.luogu.org/problemnew/show/P3224#sub 题目: 题目大意: 维护多个联通块,没有删除操作,每次询问某一联通块的第k大 解法: 维护联通 ...

  6. 【洛谷P3224】永无乡 并查集+Splay启发式合并

    题目大意:给定 N 个点的图,点有点权,初始有一些无向边,现在有 Q 个询问,每个询问支持动态增加一条无向边连接两个不连通的点和查询第 X 个点所在的联通块中权值第 K 大的是哪个点. 题解:学会了平 ...

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

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

  8. 线段树合并+并查集 || BZOJ 2733: [HNOI2012]永无乡 || Luogu P3224 [HNOI2012]永无乡

    题面:P3224 [HNOI2012]永无乡 题解: 随便写写 代码: #include<cstdio> #include<cstring> #include<iostr ...

  9. P3224 [HNOI2012]永无乡 题解

    P3224 [HNOI2012]永无乡 题解 题意概括 有若干集合,每个集合最初包含一个值,和一个编号1~n.两个操作:合并两个集合,查询包含值x的集合中第k大值最初的集合编号. 思路 维护集合之间关 ...

随机推荐

  1. 手机丢了怎么办?MZ给你来支招

    1致电运营商挂失手机 2致电银行冻结手机网银 3手机绑定支付宝的拨95188挂失 4微信用户登录110.qq.com冻结账号 5修改微博.微信.QQ等密码 6到手机运营商处补手机卡. 一定要记住啊!手 ...

  2. Hbase学习指南

    本篇Hbase组件基于CDH5进行安装,安装过程:https://www.cnblogs.com/dmjx/p/10037066.html Hbase简介 HBase是一个高可靠.高性能.面向列.可伸 ...

  3. 在唯一密钥属性“fileExtension”设置为“.”时,无法添加类型为“mimeMap”的重复集合项

    在ASP.NET 网站的配置文件中添加了MIME类型,但是运行网站后在IIS上和页面上提示"在唯一密钥属性“fileExtension”设置为“.woff”时,无法添加类型为“mimeMap ...

  4. 准备篇(二)C语言

    因为C语言部分打算单独维护,所以 目录: 1. C语言基础篇(零)gcc编译和预处理 2. C语言基础篇(一)关键字 3. C语言基础篇(二)运算符 4. C语言指针篇(一)指针与指针变量 5. C语 ...

  5. Android 自定义WebView 实现可以加载缓存数据

    1.自定义WebView说明 1.1.这个WebView可以加载缓存的数据.(需要后端配合,将html转换成一个字符串,主要是图片要用特殊格式) 1.2.注入了图片链接,为了方便点击webView中的 ...

  6. Eclipse EE 运行 Myeclipse Web 应用

    第一步:进入项目所在目录,打开.project文件,找到<natures>...</natures>标签,在中间添加如下子标签内容 <nature>org.ecli ...

  7. java前台传参json,后台用map或者实体对象接收

    (一)前台传js对象,里面包含数组,后台用map接收 (1)第一种情况:数组里不包含js对象 var param ={}: param.id=id; param.name=name; var scor ...

  8. MyEclipse - MyEclipse优化

    1.去除不需要的启动加载项 选择菜单:Window --> Preferences -->General --> Startup and Shutdown, 可以关掉的启动项有: J ...

  9. HTML5技巧

    HTML5技巧   HTML5 技巧一:当今科技发展的速度真惊人,稍不留神,就可能无法跟上它的步伐.新一代的HTML-HTML5的发展也不停的带给我们新的惊喜,我们将通过这篇文章向大家介绍一些HTML ...

  10. Jenkins拾遗--第二篇(初步配置Jenkins)

    插件配置 第一次安装Jenkins的时候会让你配置插件.这里有一个建议:就是把所有插件都看一遍,如果用不到,就不要勾选.Jenkins插件兼容性有的时候不是很好,多装多出事儿,保持最小集就好.浏览一遍 ...