题目描述:

每个小岛有一个重要度W
资瓷以下操作:
1:在 X Y 之间建一座桥梁
2:查询与 X 联通的小岛中 重要度为第K小的岛

题目分析:

看到建边就开始乱搞LCT了,雾
其实连边我们可以搞一下启Fa♂式合并(巨巨们说是一个log
1.Splay+启Fa♂式合并
我们刚开始把每个节点都当成一个独立的Splay
然后用一下并查集维护一下联通关系就好了
O(Qlogn2)O(Qlogn2)O(Qlogn^2)
2.权值线段树+启Fa♂式合并
对于每个节点建立一颗权值线段树,然后启发式合并线段树就好了。
也是用并查集维护联通关系
O(Qlogn2)O(Qlogn2)O(Qlogn^2)
我的线段树写的有点假,应该是细节处理的不好,跑的比平衡树慢一点

题目链接:

COGS 1341
Bzoj 2733
Luogu 3224

Ac 代码:

Splay

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
const int maxm=110000;
int rt[maxm];
int fa[maxm],ch[maxm][2],siz[maxm];
int w[maxm];
int Fa[maxm];
std::queue<int> dl;
inline int find(int x){return Fa[x]==x?x:Fa[x]=find(Fa[x]);}
inline bool get(int x){return (ch[fa[x]][1]==x);}
inline void pushup(int x)
{if(!x) return;siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
}
inline void rotate(int x)
{int f1=fa[x],f2=fa[f1];bool g1=get(x),g2=get(f1);ch[f1][g1]=ch[x][g1^1];fa[ch[x][g1^1]]=f1;ch[x][g1^1]=f1,fa[f1]=x;fa[x]=f2;if(f2) ch[f2][g2]=x;pushup(f1),pushup(x);
}
inline void splay(int i,int x,int top)
{for(int fax;(fax=fa[x])!=top;rotate(x))if(fa[fax]!=top) rotate(get(fax)==get(x)?fax:x);if(!top) rt[i]=x;
}
inline void insert(int x,int &now,int fat)
{if(!now){now=x;fa[now]=fat;return;}siz[now]++;if(w[x]<=w[now]) insert(x,ch[now][0],now);else insert(x,ch[now][1],now);
}
inline void merge(int x,int y)
{if(x==y) return;if(siz[rt[x]]>siz[rt[y]]) std::swap(x,y);Fa[x]=y;dl.push(rt[x]);while(!dl.empty()){int now=dl.front();dl.pop();if(ch[now][0]) dl.push(ch[now][0]);if(ch[now][1]) dl.push(ch[now][1]);insert(now,rt[y],0);splay(y,now,0);}
}
inline int find_kth(int i,int rank)
{int now=rt[i];if(siz[now]<rank) return -1;while(1){if(rank<=siz[ch[now][0]]) now=ch[now][0];else if(siz[ch[now][0]]+1==rank) return now;else rank-=siz[ch[now][0]]+1,now=ch[now][1];}
}
int main()
{//freopen("bzoj_2733.in","r",stdin);//freopen("bzoj_2733.out","w",stdout);int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) {scanf("%d",&w[i]);rt[i]=i,siz[i]=1,Fa[i]=i;}for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);merge(find(u),find(v));}int q;scanf("%d",&q);for(int i=1;i<=q;i++){char s[10];scanf("%s",s);if(s[0]=='Q'){int x,k;scanf("%d%d",&x,&k);printf("%d\n",find_kth(find(x),k));}else{int u,v;scanf("%d%d",&u,&v);merge(find(u),find(v));}}return 0;
}

权值线段树

#include <cstdio>
#include <iostream>
#include <algorithm>
const int maxm=1e6+100;
int fa[maxm];
int sum[maxm<<2],ls[maxm<<2],rs[maxm<<2],rt[maxm];
int pos[maxm];
int sz;
int n,m,q;
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void pushup(int x){sum[x]=(sum[ls[x]]+sum[rs[x]]);}
void insert(int &o,int l,int r,int ind)
{//printf("%d %d\n",l,r);if(!o) o=++sz;if(l>=r) {sum[o]++;return;}int mid=(l+r)>>1;if(ind<=mid) insert(ls[o],l,mid,ind);else insert(rs[o],mid+1,r,ind);pushup(o);
}
int merge(int o,int pre)
{if(!o||!pre) return o+pre;ls[o]=merge(ls[o],ls[pre]);rs[o]=merge(rs[o],rs[pre]);pushup(o);return o;
}
int kth(int o,int l,int r,int rank)
{if(l>=r) return l;int mid=(l+r)>>1;if(rank<=sum[ls[o]]) return kth(ls[o],l,mid,rank);else return kth(rs[o],mid+1,r,rank-sum[ls[o]]);
}
int main()
{//freopen("bzoj_2733.in","r",stdin);//freopen("bzoj_2733.out","w",stdout);scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){int w;scanf("%d",&w);pos[w]=i,fa[i]=i;insert(rt[i],1,n,w);}for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);int f1=find(u),f2=find(v);if(f1==f2) continue;fa[f1]=f2;rt[f2]=merge(rt[f1],rt[f2]);}scanf("%d",&q);for(int i=1;i<=q;i++){char s[10];scanf("%s",s);if(s[0]=='Q'){int x,k;scanf("%d%d",&x,&k);if(sum[rt[find(x)]]<k) printf("-1\n");else printf("%d\n",pos[kth(rt[find(x)],1,n,k)]);}else{int u,v;scanf("%d%d",&u,&v);int f1=find(u),f2=find(v);if(f1==f2) continue;fa[f1]=f2;rt[f2]=merge(rt[f1],rt[f2]);}}return 0;
}

[HNOI 2012] 永无乡相关推荐

  1. HNOI 2012 永无乡

    codevs 1477 永无乡 http://codevs.cn/problem/1477/ 2012年湖南湖北省队选拔赛  时间限制: 1 s  空间限制: 128000 KB 题目描述 Descr ...

  2. [HNOI 2012]永无乡

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

  3. 【HNOI 2012】永无乡

    [题目] 传送门 题目描述: 永无乡包含 nnn 座岛,编号从 111 到 nnn ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 nnn 座岛排名,名次用 111 到 nnn 来表示.某些岛 ...

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

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

  5. 数据结构之线段树合并——永无乡,Lomsat gelral,Tree Rotations,Tree Rotations Escape Through Leaf

    文章目录 [HNOI2012]永无乡 Lomsat gelral 「POI2011 R2 Day2」旋转树木 Tree Rotations Escape Through Leaf 线段树合并与 fhq ...

  6. 数据结构之fhq-treap——Chef and Sets,[HNOI2012]永无乡,Play with Chain,[NOI2005]维修数列(结构体版代码)

    因为非常板,所以主要是代码 Tyvj 1728 普通平衡树 Chef and Sets [HNOI2012]永无乡 Play with Chain [NOI2005]维修数列 题目很水,所以可能会出现 ...

  7. P3224 [HNOI2012]永无乡(并查集+权值线段树合并/平衡树)

    [HNOI2012]永无乡 Code1 权值线段树天然支持merge,线段树上二分求第k小 #include<bits/stdc++.h>using namespace std; usin ...

  8. bzoj2733永无乡

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

  9. BZOJ 2733: [HNOI2012]永无乡 启发式合并treap

    2733: [HNOI2012]永无乡 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

最新文章

  1. Android 环境搭建的错误解决方案
  2. 【c++】10. memset()、【strcpy_s()、memcpy_s()】、【strcpy(),memcpy()】
  3. 【年终总结】2019年有三AI NLP做了什么,明年要做什么?
  4. Camera Calibration and 3D Reconstruction
  5. Appium wait等待的三种方法
  6. 有两个序列a,b,大小都为n,序列元素的值任意整数,无序;要求:通过交换a,b中的元素,使[序列a元素的和
  7. 致敬 hacker |盘点内存虚拟化探索之路
  8. 深入理解Redis系列之SpringBoot集成Redis
  9. 思科cisco路由器动态路由协议配置方法
  10. 【SpringBoot】spring boot + mybatis + druid
  11. NET- SplitContainer控件说明
  12. python的时间序列,Python时间序列
  13. Tensorflow官方文档学习理解 (二)
  14. JavaScript比较是否在某时间段内
  15. 计算机视觉和机器学习,代码,论文大全
  16. VLAN介绍、工作原理以及配置
  17. (35)pycharm在debug模式下一直显示collecting data
  18. 技术领导者空降后,如何管理全新的团队
  19. 菩提千年,你是我红尘中最美的缘
  20. 谷歌浏览器点击上传文件崩溃/上传图片崩溃/打开浏览文件未响应 解决方案

热门文章

  1. [学习笔记]B站视频:磨剑之作,七周成“师”!【七周成为数据分析师】- 第一周
  2. C语言初阶——5.字符串
  3. Mycat概述及基本使用
  4. java安装和java_home,jre_home环境变量配置
  5. Chino with Triangle
  6. 牛客网在线编程专题《剑指offer-面试题39:题目二》判断是否是平衡二叉树
  7. 先学python还是ros_如何学习Ros?
  8. 带你渐入佳境,一文捋清协程
  9. VBA编程_Application
  10. 《Oracle内核技术解密》读书笔记(二)