题目大意:给你一些点,修改是在在两个点之间连一条无向边,查询时求某个点能走到的点中重要度第k大的点。题目中给定的是每个节点的排名,所以实际上是求第k小;题目求的是编号,不是重要度的排名。我一开始差点被这坑了。

  网址:http://www.lydsy.com/JudgeOnline/problem.php?id=2733

  这道题似乎挺经典的(至少我看许多神犇很早就做了这道题)。这道题有两种写法:并查集+(splay启发式合并or线段树合并)。我写的是线段树合并,因为……splay不会打+懒得学。

  线段树合并具体可以看ppt:https://wenku.baidu.com/view/88f4e134e518964bcf847c95.html(线段树的合并——杭州二中黄嘉泰)

  这道题可以一开始每个节点建一棵值域线段树(没用到的子树像trie一样,先指向null),然后合并操作就用上面文章中线段树合并的方法,同时把并查集合并一下(如果把树x合并到树y,那么在并查集里也要把fa[x]改为y,这样就能保证并查集的根和线段树的根是同一个节点),查询可以先用并查集查出这个节点属于哪棵树,然后在树上二分(就是在值域线段树上求序列第k大),然后就完了。

  P.S.似乎不加读入优化我的线段树合并要比我一位同学的splay快400ms+,不过splay很常用,还是过几天学一学吧。。。(第一行是我加了快读的线段树合并,第二行没有加快读,第三行是同学的splay)

奇丑无比的代码:

#include<cstdio>
using namespace std;
struct hh{
int lc,rc,sum;
}a[];
int rank[],id[],fa[],tot;
int read()
{
char c=getchar(),flag=;
while(c<''||''<c){
if(c=='-')flag=-; c=getchar();
}
int tmp=;
while(''<=c&&c<=''){
tmp=tmp*+c-''; c=getchar();
}
return tmp*flag;
}
void add(int now,int x,int l,int r)
{
++a[now].sum; if(l==r)return;
if(x<=(l+r)>>){
if(!a[now].lc)a[now].lc=++tot;
add(a[now].lc,x,l,(l+r)>>);
}
else{
if(!a[now].rc)a[now].rc=++tot;
add(a[now].rc,x,((l+r)>>)+,r);
}
}
int query(int now,int x,int l,int r)
{
if(l==r)return l;
if(a[a[now].lc].sum>=x)return query(a[now].lc,x,l,(l+r)>>);
else return query(a[now].rc,x-a[a[now].lc].sum,((l+r)>>)+,r);
}
void merge(int x,int y)
{
a[x].sum+=a[y].sum;
if(a[x].lc||a[x].rc){
if(a[y].lc){
if(!a[x].lc)a[x].lc=a[y].lc;
else merge(a[x].lc,a[y].lc);
}
if(a[y].rc){
if(!a[x].rc)a[x].rc=a[y].rc;
else merge(a[x].rc,a[y].rc);
}
}
}
int find(int x)
{
if(fa[x]==x)return x;
return fa[x]=find(fa[x]);
}
int main()
{
int n=read(),m=read(),i; tot=n;
for(i=;i<=n;i++){
rank[i]=read(); id[rank[i]]=fa[i]=i;
add(i,rank[i],,n);
}
for(i=;i<=m;i++){
int x=read(),y=read(),fx,fy;
fx=find(x); fy=find(y);
if(fx!=fy){
fa[fy]=fx; merge(fx,fy);
}
}
m=read();
for(i=;i<=m;i++){
char ch; scanf("%s",&ch);
int x=read(),y=read();
if(ch=='Q'){
int fx=find(x);
if(a[fx].sum<y)printf("-1\n"); else printf("%d\n",id[query(fx,y,,n)]);
}
else{
int fx=find(x),fy=find(y);
if(fx!=fy){
fa[fy]=fx; merge(fx,fy);
}
}
}
}

  splay的等学了再补吧。。。

【BZOJ2733】永无乡[HNOI2012](splay启发式合并or线段树合并)的更多相关文章

  1. BZOJ2733 永无乡【splay启发式合并】

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  2. BZOJ2733 永无乡 【splay启发式合并】

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 4190  Solved: 2226 [Submit][Sta ...

  3. 【HNOI2012】永无乡 题解(并查集+线段树合并)

    题目链接 给定一张含$n$个点$m$条边的无向图,每个点有一个重要指数$a_i$.有两种操作:1.在$x$和$y$之间连一条边:2.求$x$所在连通块中重要程度第$k$小的点. ----------- ...

  4. bzoj2733: [HNOI2012]永无乡(splay+启发式合并/线段树合并)

    这题之前写过线段树合并,今天复习Splay的时候想起这题,打算写一次Splay+启发式合并. 好爽!!! 写了长长的代码(其实也不长),只凭着下午的一点记忆(没背板子...),调了好久好久,过了样例, ...

  5. Bzoj 2733: [HNOI2012]永无乡 数组Splay+启发式合并

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

  6. 【题解】永无乡 [HNOI2012] [BZOJ2733] [P3224]

    [题解]永无乡 [HNOI2012] [BZOJ2733] [P3224] [题目描述] 永无乡包含 \(n\) 座岛,编号从 \(1\) 到 \(n\) ,每座岛都有自己的独一无二的重要度,按照重要 ...

  7. 【HNOI2012】永无乡(splay,启发式合并)

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

  8. bzoj2733 永无乡 splay树的启发式合并

    https://vjudge.net/problem/HYSBZ-2733 给一些带权点,有些点是互相连通的, 然后给出2种操作,在两点间加一条边,或者询问一个点所在的连通块内的第k小值的编号 并查集 ...

  9. [BZOJ2733][HNOI2010]永无乡 解题报告 启发式合并,线段树合并

    好久没更新博客了,前段时间一直都在考试,都没时间些,现在终于有点闲了(cai guai)... 写了一道题,[HNOI2012]永无乡,其实是一道板子题,我发现我写了好多板子题...还是太菜了... ...

随机推荐

  1. 错误命令“if not exist "\Dll" mkdir "\Dll" xcopy "\bin\Debug\*.*" "F:\647\VS项目\EtrolMes2014SY\Framework\Dll" /e /i /y”已退出,代码为 9009

    分析错误 第一步:观察错误,发现plugin文件夹中未生成对应的编译文件. 第二步:XCOPY命令无法执行,百度xcopy为何无法执行 第三步,搜索,发现环境变量未配置正确. 就是环境变量path(大 ...

  2. java中使用MD5进行加密

    java中使用MD5进行加密     在各种应用系统的开发中,经常需要存储用户信息,很多地方都要存储用户密码,而将用户密码直接存储在服务器上显然是不安全的,本文简要介绍工作中常用的 MD5加密算法,希 ...

  3. hoj 2543 (费用流 拆边)

    http://acm.hit.edu.cn/hoj/problem/view?id=2543 1.将原图中的每条边(u, v)拆成两条:(u, v, Ci, 0), (u, v, ∞, Ei) 2.购 ...

  4. 【BZOJ3502/2288】PA2012 Tanie linie/【POJ Challenge】生日礼物 堆+链表(模拟费用流)

    [BZOJ3502]PA2012 Tanie linie Description n个数字,求不相交的总和最大的最多k个连续子序列. 1<= k<= N<= 1000000. Sam ...

  5. 【BZOJ1058】[ZJOI2007]报表统计 STL

    [BZOJ1058][ZJOI2007]报表统计 Description 小Q的妈妈是一个出纳,经常需要做一些统计报表的工作.今天是妈妈的生日,小Q希望可以帮妈妈分担一些工作,作为她的生日礼物之一.经 ...

  6. n++ ++n

    n = 100 + m++ n = 100 +m; ++m n = 100 + ++m; ++m; n = 100 +m ;

  7. C# new和override区别(转)

    override 1. override是派生类用来重写基类中方法的: 2. override不能重写非虚方法和静态方法: 3. override只能重写用virtual.abstract.overr ...

  8. 原文来自 url get

    w http://www.tuicool.com/articles/BvYbEvR http://36kr.com/p/5069371.html?utm_source=tuicool&utm_ ...

  9. 涉及到复制和二进制日志中的选项和变量-Replication and Binary Logging Options and Variables

    在搭建复制中,有些参数需要我们留意,在这里罗列出来,供大家参考一下,以GTID为基础 --server-id server-id:这是一个全局的可动态调整的变量,取值范围为0-4294967295,也 ...

  10. Dockerfile学习(二)

    这节学习制作一个ssh镜像服务. 创建sshtest目录,进入到该目录中. 假如允许主机B上的root用户可以通过SSH登录到容器内部,那么首先要在B主机上通过ssh-keygen -t rsa命令生 ...