这次我们来搞一个很新奇的知识点:克鲁斯卡尔重构树。它也是一种图,是克鲁斯卡尔算法求最小生成树的升级版首先看下面一个问题:BZOJ3545 Peaks。

在Bytemountains有N座山峰,每座山峰有他的高度h_i。有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走。

现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1。N<=1e5,M,Q<=5*1e5

上面这个题没有要求在线,因此我们可以离线构造最小生成树,然后当小于等于一个询问的困难值的所有边都加入后,就可以查询当前的询问点。

这种操作只需要主席树上树+启发式合并就可以解决了。(参考资料:主席树上树http://www.cnblogs.com/LadyLex/p/7275164.html,启发式合并http://www.cnblogs.com/LadyLex/p/7275793.html

但是如果强制在线呢?BZOJ3551 Peaks加强版,在上一题基础上强制在线。

可以用来解决一系列“查询从某个点出发经过边权不超过val的边所能到达的节点”的问题,可以和其他数据结构(比如主席树)套用来维护更加复杂的询问。

克鲁斯卡尔重构树的核心思想是,当添加最小生成树中的边的时候,不在两个点间直接加边,而是新建节点,让边的两个端点所在的联通块的代表点分别作为它的左右儿子节点,然后这个新建的点,就成为这整个连通块的代表点,点权为连边的值(最开始n个叶子节点点权为0)。比如看下面这张图:首先连接(1,2),新建一个点5。再连接(3,4),新建一个点6。然后连接(1,3),连接它们各自联通块的代表点(5,6),再新建一个点7。

这样得到的树有一个很优雅的性质:一个点的所有子树节点的权值都小于等于它的权值,并且从它开始逐渐向子节点移动,权值是单调不上升的。这个性质是显然的,因为我们在构造树的时候是从小到大插入的边,因此父亲节点的权值一定大于等于子节点的值。

查询时,首先可以在树上倍增得到当前查询点所能够到达的最远的祖先点,那么从这个点能够到达的符合边权限制条件的连通块中的节点,就是祖先点的子树中所有的叶节点。

然后我们按dfs序维护一个主席树上树就可以解决了。

代码见下:

 #include <cstring>
#include <cstdio>
#include <algorithm>
#include <ctime>
using namespace std;
const int N=;
int h[N*],val[N*],n,tot,num,cnt,stack[N],e,adj[N*];
int f[N*][],bin[],fa[N*],l[N*],r[N*];
struct edge{int qi,zhong,val;}intn[N*];
struct link{int zhong,next;}s[N*];
inline void mission1(int rt){for(int i=;bin[i]<=n;i++)f[rt][i]=f[f[rt][i-]][i-];}
inline void add(int qi,int zhong){s[++e].zhong=zhong;s[e].next=adj[qi];adj[qi]=e;}
inline bool mt(const edge &a,const edge &b){return a.val<b.val;}
int find(int a){return (fa[a]==a)?a:fa[a]=find(fa[a]);}
struct node
{
int cnt;node *ch[];
node(){cnt=;ch[]=ch[]=NULL;}
inline void update(){cnt=ch[]->cnt+ch[]->cnt;}
}*null=new node(),*root[*N];
inline node* newnode(){node *o=new node();o->ch[]=o->ch[]=null;return o;}
void insert(node *&o,node *old,int l,int r,int pos)
{
o->cnt=old->cnt+;
if(l==r)return;
int mi=(l+r)>>;
if(pos<=mi)o->ch[]=old->ch[],o->ch[]=newnode(),insert(o->ch[],old->ch[],l,mi,pos);
else o->ch[]=old->ch[],o->ch[]=newnode(),insert(o->ch[],old->ch[],mi+,r,pos);
o->update();
}
inline int query(int a,int x,int k)
{
int le=,ri=tot;
for(int j=;~j;j--)
    if(f[a][j]&&val[f[a][j]]<=x)a=f[a][j];
node *a1=root[r[a]],*a2=root[l[a]-];
if(a1->cnt-a2->cnt<k)return -;
while(le<ri)
{
int tmp=a1->ch[]->cnt-a2->ch[]->cnt,mi=(le+ri)>>;
if(tmp>=k)a1=a1->ch[],a2=a2->ch[],le=mi+;
else a1=a1->ch[],a2=a2->ch[],k-=tmp,ri=mi;
}
return stack[ri];
}
void dfs(int rt)
{
mission1(rt);l[rt]=++num;
if(rt<=n)insert(root[num],root[num-],,tot,h[rt]);
else root[num]=root[num-];
for(int i=adj[rt];i;i=s[i].next)dfs(s[i].zhong);
r[rt]=num;
}
int main()
{
int m,q,ans=,v,x,k;scanf("%d%d%d",&n,&m,&q);
bin[]=;for(int i=;i<=;i++)bin[i]=bin[i-]<<;
null->ch[]=null->ch[]=null;
for(int i=;i<=n*;i++)fa[i]=i;
for(int i=;i<=n;i++)scanf("%d",&h[i]),stack[i]=h[i];
for(int i=;i<=m;i++)scanf("%d%d%d",&intn[i].qi,&intn[i].zhong,&intn[i].val);
sort(stack+,stack+n+);
tot=unique(stack+,stack+n+)-stack-;
for(int i=;i<=n;i++)h[i]=lower_bound(stack+,stack+tot+,h[i])-stack;
sort(intn+,intn+m+,mt);cnt=n;
for(int i=;i<=m;i++)
{
int u=find(intn[i].qi),v=find(intn[i].zhong);
if(u!=v)
{
val[++cnt]=intn[i].val,fa[u]=fa[v]=cnt;
add(cnt,u),add(cnt,v),f[u][]=f[v][]=cnt;
if(cnt-n==n-)break;
}
}
for(int i=;i<=cnt;i++)root[i]=newnode();
for(int i=;i<=cnt;i++)if(!l[i])dfs(find(i));
while(q--)
{
scanf("%d%d%d",&v,&x,&k);
if(ans!=-)v^=ans,x^=ans,k^=ans;/*去掉这句强制在线可以ACbzoj3545*/
printf("%d\n",ans=query(v,x,k));
}
}

克鲁斯卡尔重构树是个比较小众的知识点,但在处理对口的操作时十分强大。下次你再看到类似询问的时候,不妨想一想克鲁斯卡尔重构树,也许就会柳暗花明又一村:)

[您有新的未分配科技点][BZOJ3545&BZOJ3551]克鲁斯卡尔重构树的更多相关文章

  1. [您有新的未分配科技点] 无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MB Description Input 输入的第1 行包含两个数N 和M(M ≤20 ...

  2. [您有新的未分配科技点]博弈论进阶:似乎不那么恐惧了…… (SJ定理,简单的基础模型)

    这次,我们来继续学习博弈论的知识.今天我们会学习更多的基础模型,以及SJ定理的应用. 首先,我们来看博弈论在DAG上的应用.首先来看一个小例子:在一个有向无环图中,有一个棋子从某一个点开始一直向它的出 ...

  3. [您有新的未分配科技点]博弈论入门:被博弈论支配的恐惧(Nim游戏,SG函数)

    今天初步学习了一下博弈论……感觉真的是好精妙啊……希望这篇博客可以帮助到和我一样刚学习博弈论的同学们. 博弈论,又被称为对策论,被用于考虑游戏中个体的预测行为和实际行为,并研究他们的应用策略.(其实这 ...

  4. [您有新的未分配科技点]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)

    今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和treap一样简单易懂,同时还支持可持久化. 无旋treap的节点定义和treap一样,都要同时满足树性质和堆性质,我 ...

  5. [您有新的未分配科技点]可,可,可持久化!?------0-1Trie和可持久化Trie普及版讲解

    这一次,我们来了解普通Trie树的变种:0-1Trie以及在其基础上产生的可持久化Trie(其实,普通的Trie也可以可持久化,只是不太常见) 先简单介绍一下0-1Trie:一个0-1Trie节点只有 ...

  6. [您有新的未分配科技点]数位DP:从板子到基础(例题 bzoj1026 windy数 bzoj3131 淘金)

    只会统计数位个数或者某种”符合简单规律”的数并不够……我们需要更多的套路和应用 数位dp中常用的思想是“分类讨论”思想.下面我们就看一道典型的分类讨论例题 1026: [SCOI2009]windy数 ...

  7. [您有新的未分配科技点]数位dp:从懵X到板子(例题:HDU2089 不要62)

    数位dp主要用来处理一系列需要数数的问题,一般套路为“求[l,r]区间内满足要求的数/数位的个数” 要求五花八门……比如“不出现某个数字序列”,“某种数的出现次数”等等…… 面对这种数数题,暴力的想法 ...

  8. 【BZOJ3545】Peaks(Kruskal重构树 主席树)

    题目链接 大意 给出有\(N\)个点\(M\)条边的一张图,其中每个点都有一个High值,每条边都有一个Hard值. 再给出\(Q\)个询问:\(v\) \(x\) \(k\) 每次询问查询从点\(v ...

  9. Elasticsearch 学习之 分片未分配原因

    分片未分配的原因主要有: 1)INDEX_CREATED:由于创建索引的API导致未分配.2)CLUSTER_RECOVERED :由于完全集群恢复导致未分配.3)INDEX_REOPENED :由于 ...

随机推荐

  1. 安全测试 WEB安全测试手册

    WEB安全测试手册 By:授客 QQ:1033553122 欢迎加入软件性能测试交流QQ群:7156436 概述 Ø          目的 Ø          适用读者 Ø          适用 ...

  2. 微信小程序-01-项目组成文件介绍(入门篇)

    自古开篇先说两句,写这些笔记不是学习用的,主要是后续分享一些遇到的坑,碰到过什么样的问题,怎么去解决,如果你不是一个很耐心无看文章的人,建议去 网易云课堂找一些课程,跟着别人的脚步或许会更有动力,我的 ...

  3. Windows 10 执行pip list报错 UnicodeDecodeError: 'gbk' codec can't decode

    在命令行执行任何pip命令都报错: C:\Users\hyang0>pip --version Traceback (most recent call last): File "c:\ ...

  4. kettle用mysql创建资源库执行sql代码报错

    一.原因:  sql语句里边使用 'Y' 'N'  给boolean类型的赋值产生sql失败    二.解决方法:将insert语句中‘Y’或‘N’ 改成TRUE或FALSE即可,共两张表3个地方  ...

  5. 【PAT】B1068 万绿丛中一点红(20 分)

    一开始因为看见这题就头疼,可费了点时间. 要考虑所有元素,如果忽略外圈元素,最后一个样例过不去. 而且要求只出现一次的元素, 我没有使用map,因为当时还没学,用map储存元素会节约好多代码 #inc ...

  6. 01LaTeX学习系列之---TeX的介绍与认识

    目录 01TeX的介绍与认识 目录 前言 (一)TeX 的宣传 TeX - Beauty and Fun 1. TeX 是什么? 2. TeX 是哪家公司生产的? 3. 我们今天主角的名字怎么念啊?& ...

  7. Hadoop2.7.6_06_mapreduce参数优化

    MapReduce重要配置参数 1. 资源相关参数 //以下参数是在用户自己的mr应用程序中配置就可以生效 () mapreduce.map.memory.mb: 一个Map Task可使用的资源上限 ...

  8. <!DOCTYPE>标签与table高度100% (转)

    <!DOCTYPE>标签可声明三种DTD类型,分别表示严格版本.过渡版本以及基于框架的 HTML 文档. 三种HTML文档类型: HTML 4.01 规定了三种文档类型:Strict.Tr ...

  9. leetcode 395. Longest Substring with At Least K Repeating Characters(高质量题)

    只能说还是太菜,抄的网上大神的做法: idea: mask 的每一位代表该位字母够不够k次,够k次为0,不够为1 对于每一位将其视为起点,遍历至末尾,找到其最大满足子串T的下标max_idx,之后从m ...

  10. 使用vue-cli脚手架创建的项目结构详解

    项目整体目录结构预览 src目录 src整体结构 开发过程中基本上操作都在该目录下进行操作的,项目所有源码都是在这个目录下 main.js文件,项目核心文件 App.vue文件,项目入口文件 rout ...