bzoj3545-bzoj3551-Peaks

时间:2022-12-18 13:07:18

题意

给出一个图,边有边权,点有点权,每次询问一个点 \(x\) 只走边权小于等于 \(d\) 的边能到达的点中点权第 \(k\) 大。

强制在线,\(n\le 10^5,m,q\le 5\times 10^5\)

分析

如果可以离线的话,我们可以用一个并查集(路径压缩)维护连通性,在并查集的每个点上存一个权值线段树,每次merge的时候就把下面的线段树合并到上面。做kruskal最小生成树,从小到大每次加完一种权值的边后处理这里的询问。这样的复杂度为 \(O(n\log n\alpha(n))\) 。

然而现在是强制在线,引入一种新的数据结构——kruskal重构树(我也不知道为什么是这个名字)。它的思想非常简单。kruskal的时候我们是从小到大添加边,那么我们还是用类似并查集的方法,每次合并的时候新建一个点,把需要合并的两个点都挂在这个新点的下面,新点的权值为这条边的边权。这样我们会得到一棵树,它满足新点的结构组成一个大根堆。那么如果我们要查询从一个点出发,边权小于等于 \(d\) 的边能到达的点,其实就是从这个点不断往上跳,保证经过的每个新点 \(p\) 的权值都小于等于 \(d\) 。最后走到的这个新点的整个子树就是我们能够走到的点。

由于这棵树的高度没有保证,我们把这棵树建出来,做一个可持久化线段树的合并,倍增跳到合法的 \(p\) ,查询子树即可。复杂度为 \(O(n\log n)\),非常优秀。

其实这题我还有一个想法。我们每次不新建点,而是按秩合并并查集,在每个点上开一个map,记录一下每个权值对应的线段树根,每次暴力往上跳到合法位置,在map上lower_bound以下,直接查询即可。复杂度也为 \(O(n\log n)\) 。

代码

这不是kruskal重构树,是我那个方法。

#include<bits/stdc++.h>
using namespace std;
inline char nchar() {
static const int bufl=1<<20;
static char buf[bufl],*a,*b;
return a==b && (b=(a=buf)+fread(buf,1,bufl,stdin),a==b)?EOF:*a++;
}
inline int read() {
int x=0,f=1;
char c=nchar();
for (;!isdigit(c);c=nchar()) if (c=='-') f=-1;
for (;isdigit(c);c=nchar()) x=x*10+c-'0';
return x*f;
}
inline void write(int x) {
if (x==0) puts("0"); else if (x==-1) puts("-1"); else {
static char s[20];
int tot=0;
for (;x;x/=10) s[++tot]=x%10+'0';
while (tot) putchar(s[tot--]);
puts("");
}
}
const int maxn=1e5+1;
const int maxm=5e5+1;
const int inf=1e9+7;
int h[maxn],c[maxn],ls=0,n,m,q;
pair<int,pair<int,int> > e[maxm];
namespace sgt {
const int maxp=5e6+1;
struct node {
int l,r,size;
} t[maxp];
int tot=0;
void inc(int &x,int l,int r,int p) {
if (!x) x=++tot;
++t[x].size;
if (l==r) return;
int mid=(l+r)>>1;
p<=mid?inc(t[x].l,l,mid,p):inc(t[x].r,mid+1,r,p);
}
inline void inc(int &x,int p) {inc(x,1,ls,p);}
int merge(int x,int y,int l,int r) {
if (!x) return y;
if (!y) return x;
int p=++tot,mid=(l+r)>>1;
if (l==r) {
t[p].size=t[x].size+t[y].size;
return p;
}
t[p].l=merge(t[x].l,t[y].l,l,mid);
t[p].r=merge(t[x].r,t[y].r,mid+1,r);
t[p].size=t[t[p].l].size+t[t[p].r].size;
return p;
}
int query(int x,int l,int r,int k) {
if (l==r) return l;
int mid=(l+r)>>1;
return k<=t[t[x].l].size?query(t[x].l,l,mid,k):query(t[x].r,mid+1,r,k-t[t[x].l].size);
}
inline int query(int x,int k) {
if (k==0 || k>t[x].size) return -1;
return query(x,1,ls,t[x].size-k+1);
}
}
namespace st {
int rk[maxn],f[maxn],w[maxn],last[maxn];
map<int,int> mp[maxn];
inline void init(int n) {for (int i=1;i<=n;++i) rk[i]=0,w[i]=-1,f[i]=i;}
int find(int x,int d=inf) {
for (;f[x]!=x && w[x]<=d;x=f[x]);
return x;
}
int uni(int x,int y,int v) {
if (rk[x]>rk[y]) swap(x,y);
f[x]=y,w[x]=v,rk[y]+=(rk[x]==rk[y]);
int tmp=mp[y].rbegin()->second;
int &rt=mp[y][v];
rt=sgt::merge(rt?rt:tmp,mp[x].rbegin()->second,1,ls);
}
int query(int x,int val,int k) {
int fx=find(x,val);
map<int,int>::iterator it=mp[fx].upper_bound(val);
int rt=(--it)->second;
return sgt::query(rt,k);
}
}
inline bool cmp(int x,int y) {return st::rk[x]<st::rk[y];}
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
n=read(),m=read(),q=read();
st::init(n);
for (int i=1;i<=n;++i) c[++ls]=h[i]=read();
sort(c+1,c+ls+1),ls=unique(c+1,c+ls+1)-c-1;
for (int i=1;i<=n;++i) h[i]=lower_bound(c+1,c+ls+1,h[i])-c;
for (int i=1;i<=m;++i) {
int x=read(),y=read(),w=read();
e[i]=make_pair(w,make_pair(x,y));
}
sort(e+1,e+m+1);
for (int i=1;i<=n;++i) {
sgt::inc(st::mp[i][-1],h[i]);
}
for (int i=1;i<=m;++i) {
int &w=e[i].first,&x=e[i].second.first,&y=e[i].second.second;
int fx=st::find(x),fy=st::find(y);
if (fx!=fy) st::uni(fx,fy,w);
}
int ans=0;
while (q--) {
int x=read()^ans,val=read()^ans,k=read()^ans;
ans=st::query(x,val,k);
if (ans!=-1) ans=c[ans];
write(ans);
if (ans==-1) ans=0;
}
return 0;
}

bzoj3545-bzoj3551-Peaks的更多相关文章

  1. &lbrack;您有新的未分配科技点&rsqb;&lbrack;BZOJ3545&amp&semi;BZOJ3551&rsqb;克鲁斯卡尔重构树

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

  2. bzoj3545&colon; &lbrack;ONTAK2010&rsqb;Peaks 重构树 主席树

    题目链接 bzoj3545: [ONTAK2010]Peaks 题解 套路重构树上主席树 代码 #include<cstdio> #include<algorithm> #de ...

  3. &lbrack;BZOJ3551&rsqb;Peaks

    [BZOJ3551]Peaks BZOJ luogu 建Kruskal重构树,点权为边权 按dfn序建出主席树 倍增找到能跳到的最浅的祖先 主席树查询一下 #include<bits/stdc+ ...

  4. 【bzoj3545&sol;bzoj3551】&lbrack;ONTAK2010&rsqb;Peaks&sol;加强版 Kruskal&plus;树上倍增&plus;Dfs序&plus;主席树

    bzoj3545 题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询 ...

  5. bzoj3545 &lbrack;ONTAK2010&rsqb;Peaks、bzoj3551 &lbrack;ONTAK2010&rsqb;Peaks加强版

    题目描述: bzoj3545,luogu bzoj3551 题解: 重构树+线段树合并. 可以算是板子了吧. 代码(非强制在线): #include<cstdio> #include&lt ...

  6. 【BZOJ3545&amp&semi;BZOJ3551】Peaks(kruskal重构树,主席树,dfs序)

    题意:在Bytemountains有N座山峰,每座山峰有他的高度h_i. 有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走, 现在有Q组询问,每组询问询问从点v开始只 ...

  7. BZOJ3545 &lbrack;ONTAK2010&rsqb;Peaks kruskal 并查集 主席树 dfs序

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3545 题意概括 Description 在Bytemountains有N座山峰,每座山峰有他的高度 ...

  8. bzoj3551 Peaks加强版

    这个题--感觉离线和在线的代码难度差不多(pb_ds不要说话). 离线的话,就是把所有询问按照w排个序,然后一边Kruskal+平衡树启发式合并一边回答询问就好了. 在线也不难写.首先Kruskal重 ...

  9. bzoj3545&colon; &lbrack;ONTAK2010&rsqb;Peaks

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

  10. 2018&period;09&period;30 bzoj3551&colon;Peaks加强版(dfs序&plus;主席树&plus;倍增&plus;kruskal重构树)

    传送门 一道考察比较全面的题. 这道题又用到了熟悉的kruskal+倍增来查找询问区间的方法. 查到询问的子树之后就可以用dfs序+主席树统计答案了. 代码: #include<bits/std ...

随机推荐

  1. Java浮点数float,bigdecimal和double精确计算的精度误差问题总结

    (转)Java浮点数float,bigdecimal和double精确计算的精度误差问题总结 1.float整数计算误差 案例:会员积分字段采用float类型,导致计算会员积分时,7位整数的数据计算结 ...

  2. React Native填坑之旅--布局篇

    代码在这里: https://github.com/future-challenger/petshop/tree/master/client/petshop/src/controller 回头看看RN ...

  3. 树形DP&plus;RMQ&plus;单调队列(Bob’s Race HDU4123)

    题意:有n个房子,这些房子被n-1条道路连接,有一些运动员从一个房子为起点尽可能跑最远的距离且不能通过一条道路超过两次,这些运行员不能选择同样的起点,这些运动员跑的最远距离和最近距离的差值不能超过Q, ...

  4. 【git】切换分支获取代码

    Welcome to Git (version 1.9.5-preview20150319) Run 'git help git' to display the help index.Run 'git ...

  5. NG2入门 - 架构

    AngularJS2 学习 继TypeScript之后,终于到了ng2的学习路程,同样学习根据angular官网文档进行,对文档中的内容根据自己的理解略有改动.看官可看官网文档,也可以看本系列博文 首 ...

  6. 向openwrt 源码添加ap143支持

    借鉴地址:http://www.pppei.net/blog/post/536 1.向文件 \target\linux\ar71xx\generic\profiles\atheros.mk 中添加ap ...

  7. Spring-注解实现IOC

    一.定义 注解:是一种标记式的配置方式,与XML配置文件不同,注解提供了更大的便捷性,易于维护修改,但是耦合度高. 本质:是一个继承了 Annotation 接口的接口,注解本身并没有什么作用,通过特 ...

  8. javascript基础 之 表单

    1,js可以验证表单 实例1,js获取表单的内容 //html表单是这样的 <form name="myForm" action="demo_form.php&qu ...

  9. 安装owncloud作为自己的云服务器

    环境:centos7,php5.6.37,apache2.4.6 首先,环境都要搭好,与之前搭wordpress网站是一样的.接下来下载程序 wget https://download.ownclou ...

  10. ssm框架的整合搭建(三)

    mybatis逆向工程工具类的使用---mybatis  generator 项目结构 配置文件 <?xml version="1.0" encoding="UTF ...