题目大意:

在$n$个带权点上维护两个操作:

  1)在点$u,v$间连一条边;

  2)询问点$u$所在联通块中权值第$k$小的点的编号,若该联通块中的点的数目小于$k$,则输出$-1$;


传送门

上周的模拟赛在一道线段树合并的题目上gg了,来学习一个。

对每一个联通块,我们维护一棵权值线段树。查询时,若左子树大小大于等于$k$进入左子树,否则进入右子树;

因为每棵线段树同构,所以对于任意两棵线段树可以进行合并操作:

  1. int merge(int x,int y){
  2. if(!x)return y;
  3. if(!y)return x;
  4. t[x].lson=merge(t[x].lson,t[y].lson);
  5. t[x].rson=merge(t[x].rson,t[y].rson);
  6. t[x].s=t[t[x].lson].s+t[t[x].rson].s;
  7. return x;
  8. }

利用并查集判断两个点是否连通,若不联通,则合并两个联通块的线段树即可;

代码:

  1. #include<cstring>
  2. #include<cmath>
  3. #include<cstdio>
  4. #include<algorithm>
  5. #include<cctype>
  6. #define foru(i,x,y) for(int i=x;i<=y;i++)
  7. using namespace std;
  8. const int N=1e5+;
  9.  
  10. struct node{int s,lson,rson;}t[N*];
  11. int n,m,a[N],f[N],fx,fy,cnt,rt[N],idx[N];
  12.  
  13. int gf(int k){return k==f[k]?k:f[k]=gf(f[k]);}
  14.  
  15. int read(){
  16. static int f,x;static char ch;
  17. x=f=;ch=getchar();
  18. while(!isdigit(ch)){f=(ch=='-');ch=getchar();}
  19. while(isdigit(ch)){x=x*+ch-'';ch=getchar();}
  20. return f?-x:x;
  21. }
  22.  
  23. #define ls t[k].lson
  24. #define rs t[k].rson
  25. #define mid ((L+R)>>1)
  26.  
  27. void upd(int &k,int L,int R,int p){
  28. if(p<L||p>R)return;
  29. if(!k)k=++cnt;
  30. if(L==R){t[k].s=;return;}
  31. upd(ls,L,mid,p);upd(rs,mid+,R,p);
  32. t[k].s=t[ls].s+t[rs].s;
  33. }
  34.  
  35. int query(int k,int L,int R,int p){
  36. if(L==R)return L;
  37. if(t[ls].s<p)return query(rs,mid+,R,p-t[ls].s);
  38. return query(ls,L,mid,p);
  39. }
  40.  
  41. int merge(int x,int y){
  42. if(!x)return y;
  43. if(!y)return x;
  44. t[x].lson=merge(t[x].lson,t[y].lson);
  45. t[x].rson=merge(t[x].rson,t[y].rson);
  46. t[x].s=t[t[x].lson].s+t[t[x].rson].s;
  47. return x;
  48. }
  49.  
  50. int main(){
  51. //freopen("1.in","r",stdin);
  52. memset(t,,sizeof(t));
  53. n=read();m=read();
  54. foru(i,,n)a[i]=read(),f[i]=i;
  55. foru(i,,m){
  56. fx=gf(read());fy=gf(read());
  57. f[fx]=fy;
  58. }
  59. foru(i,,n){
  60. upd(rt[gf(i)],,n,a[i]);
  61. idx[a[i]]=i;
  62. }
  63. int q=read(),x,y;
  64. char ch[];
  65. while(q--){
  66. scanf("%s%d%d",ch,&x,&y);
  67. fx=gf(x);fy=gf(y);
  68. if(ch[]=='Q')
  69. printf("%d\n",t[rt[fx]].s>=y?idx[query(rt[fx],,n,y)]:-);
  70. else if(fx!=fy){
  71. f[fx]=fy;
  72. rt[fy]=merge(rt[fx],rt[fy]);
  73. }
  74. }
  75. return ;
  76. }

BZOJ2733 [HNOI2012]永无乡(并查集+线段树合并)的更多相关文章

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

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

  2. bzoj 2733 永无乡 - 并查集 - 线段树

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

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

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

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

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

  5. BZOJ 3910 并查集+线段树合并

    思路: 1. 并查集+线段树合并 记得f[LCA]==LCA的时候 f[LCA]=fa[LCA] 2.LCT(并不会写啊...) //By SiriusRen #include <cstdio& ...

  6. bzoj2733 / P3224 [HNOI2012]永无乡(并查集+线段树合并)

    [HNOI2012]永无乡 每个联通块的点集用动态开点线段树维护 并查集维护图 合并时把线段树也合并就好了. #include<iostream> #include<cstdio&g ...

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

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

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

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

  9. [Bzoj2733][Hnoi2012] 永无乡(BST)(Pb_ds tree)

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

随机推荐

  1. HZNU-ACM寒假集训Day3小结 搜索

    简单搜索 1.DFS UVA 548 树 1.可以用数组方式实现二叉树,在申请结点时仍用“动态化静态”的思想,写newnode函数 2.给定二叉树的中序遍历和后序遍历,可以构造出这棵二叉树,方法是根据 ...

  2. Day 11:静态导入、增强for循环、可变参数的自动装箱与拆箱

    jdk1.5新特性-------静态导入 静态导入的作用: 简化书写. 静态导入可以作用一个类的所有静态成员.  静态导入的格式:import static 包名.类名.静态的成员: 静态导入要注意的 ...

  3. HttpClient系列~StringContent与FormUrlEncodedContent

    知识点 本文是一个很另类的文章,在项目中用的比较少,但如果项目中真的出现了这种情况,我们也需要知道如何去解决,对于知识点StringContent和FormUrlEncodedContent我们应该了 ...

  4. php日期时间戳,日期函数使用

    date_default_timezone_get():获得当前php的时区 date_default_timezone_set():设置当前php的时区 date("Y-m-d H-i-s ...

  5. 查找ARP攻击源

    问题: 内网有电脑中了ARP病毒,但是网络拓扑比较复杂.电脑数量较多,排查起来很困难.有什么方法可以找出ARP攻击源?[推荐3]排查方法: 1.使用Sniffer抓包.在网络内任意一台主机上运行抓包软 ...

  6. Linux--计划任务未执行

    参考:http://blog.csdn.net/shangdiyisi/article/details/9477521 日志 /var/log/cron

  7. SpringBoot+SpringSecurity+jwt整合及初体验

    原来一直使用shiro做安全框架,配置起来相当方便,正好有机会接触下SpringSecurity,学习下这个.顺道结合下jwt,把安全信息管理的问题扔给客户端, 准备 首先用的是SpringBoot, ...

  8. DRF-JWT

    DRF-JWT 一.JWT JWT全称: json web token, 作用:将原始的数据json加密成字符串,通过后台将加密的字符串给前台存储(token) 格式:三段式,头.载荷.签名 , 头和 ...

  9. 当初希望自己是如何投入这个专业的学习的?曾经做过什么准备,或者立下过什么FLAG吗?

    学习好累,打游戏好爽  我不爱学习 认真勤勉投入学习 精心准备,刻苦学习 我的flag   作为大学生,需要了解今后职场社会,对职业方向有了进一步的认识.社会对于人才的要求在某些方面都是不谋而合的,比 ...

  10. PHP的isset()函数 一般用来检测变量是否设置

    PHP的isset()函数 一般用来检测变量是否设置 格式:bool isset ( mixed var [, mixed var [, ...]] ) 功能:检测变量是否设置 返回值: 若变量不存在 ...