BZOJ3545&3551[ONTAK2010]Peaks——kruskal重构树+主席树+dfs序+树上倍增
题目描述
在Bytemountains有N座山峰,每座山峰有他的高度h_i。有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1。
输入
第一行三个数N,M,Q。
第二行N个数,第i个数为h_i
接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径。
接下来Q行,每行三个数v x k,表示一组询问。
输出
对于每组询问,输出一个整数表示答案.(3551强制在线)
样例输入
1 2 3 4 5 6 7 8 9 10
1 4 4
2 5 3
9 8 2
7 8 10
7 1 4
6 7 1
6 4 8
2 1 5
10 8 10
3 4 7
3 4 6
1 5 2
1 5 6
1 5 8
8 9 2
样例输出
1
-1
8
【数据范围】
N<=10^5, M,Q<=5*10^5,h_i,c,x<=10^9。
题意要求找出所有与一个点u路径上最大边权小于等于x的点中点权第k大。在这里先介绍一个东西叫做kruskal重构树,kruskal重构树就是将kruskal得到的最小生成树按边权从小到大进行重构,对于一条边a——b边权为c,先建一个新节点x,点权为c,然后把a,b在重构树中所在子树的根节点分别连到x的下面,作为x的左右子树,最后将所有最小生成树的边都重构完之后所得到的树就是kruskal重构树。例如样例所建的重构树如下图所示,其中黑色点为原最小生成树的点,红色点为原最小生成树的边在重构树中对应的点,黑色点内数是原树点的编号,红色点内数是原树对应边边权。

kruskal重构树有几个性质:
1、这是一棵二叉树且也是一个大根堆。
2、任意两个叶子节点在原树中路径上最大边权值为这两个点在重构树上lca的点权。
3、原树两点间路径边权最大值等于重构树中两点间路径点权最大值。
4、任意一个非叶子节点的子树中所有的叶子节点中,任意两个节点在原树中路径上边权最大值小于等于这个非叶子节点的点权(本题的关键)。
按dfs序把所有重构树上叶子节点排序,对于每次询问在重构树上倍增找到小于等于x的深度最浅的点a,利用主席树在a点子树所在dfs序的那段区间上求第k大的点就行了。注意题中没说明整张图联通。
最后附上代码(强制在线)。
#include<map>
#include<set>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define mid (L+R)/2
using namespace std;
int cnt;
int tot;
int num;
int top;
int ans;
int x,y,z;
int n,m,k;
int a[200010];
int d[200010];
int b[200010];
int q[200010];
int g[200010];
int s[200010];
int t[200010];
int v[200010];
int h[200010];
int to[800010];
int l[6000010];
int r[6000010];
int vis[200010];
int head[200010];
int next[800010];
int sum[6000010];
int root[200010];
int f[200010][20];
struct edge
{
int x;
int y;
int z;
}e[1000010];
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int find(int x)
{
if(g[x]==x)
{
return x;
}
return g[x]=find(g[x]);
}
int ST(int x,int y)
{
for(int i=19;i>=0;i--)
{
if(d[x]>=b[i]&&v[f[x][i]]<=y)
{
x=f[x][i];
}
}
return x;
}
void add(int x,int y)
{
tot++;
next[tot]=head[x];
head[x]=tot;
to[tot]=y;
}
bool cmp(edge a,edge b)
{
return a.z<b.z;
}
void dfs(int x)
{
vis[x]=1;
if(x<=n)
{
top++;
q[top]=x;
}
else
{
s[x]=top;
}
for(int i=1;i<=19;i++)
{
if(d[x]>=b[i])
{
f[x][i]=f[f[x][i-1]][i-1];
}
else
{
break;
}
}
for(int i=head[x];i;i=next[i])
{
d[to[i]]=d[x]+1;
f[to[i]][0]=x;
dfs(to[i]);
}
if(x>n)
{
t[x]=top;
}
}
int build(int L,int R)
{
int rt=++cnt;
sum[rt]=0;
if(L<R)
{
l[rt]=build(L,mid);
r[rt]=build(mid+1,R);
}
return rt;
}
int updata(int pre,int L,int R,int x)
{
int rt=++cnt;
l[rt]=l[pre];
r[rt]=r[pre];
sum[rt]=sum[pre]+1;
if(L<R)
{
if(x<=mid)
{
l[rt]=updata(l[pre],L,mid,x);
}
else
{
r[rt]=updata(r[pre],mid+1,R,x);
}
}
return rt;
}
int query(int ll,int rr,int L,int R,int k)
{
if(L>=R)
{
return L;
}
int x=sum[l[rr]]-sum[l[ll]];
if(x>=k)
{
return query(l[ll],l[rr],L,mid,k);
}
else
{
return query(r[ll],r[rr],mid+1,R,k-x);
}
}
int main()
{
b[0]=1;
for(int i=1;i<=19;i++)
{
b[i]=b[i-1]<<1;
}
n=read();
m=read();
k=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
h[i]=a[i];
}
sort(h+1,h+1+n);
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(h+1,h+n+1,a[i])-h;
}
for(int i=1;i<=2*n;i++)
{
g[i]=i;
}
for(int i=1;i<=m;i++)
{
e[i].x=read();
e[i].y=read();
e[i].z=read();
}
num=n;
sort(e+1,e+m+1,cmp);
for(int i=1;i<=m;i++)
{
int fx=find(e[i].x);
int fy=find(e[i].y);
if(fx!=fy)
{
num++;
g[fx]=g[fy]=num;
v[num]=e[i].z;
add(num,fx);
add(num,fy);
if(num==2*n-1)
{
break;
}
}
}
for(int i=1;i<=n;i++)
{
if(!vis[i])
{
dfs(find(i));
}
}
root[0]=build(1,n);
for(int i=1;i<=top;i++)
{
root[i]=updata(root[i-1],1,n,a[q[i]]);
}
while(k--)
{
x=read();
y=read();
z=read();
if(ans!=-1)
{
x^=ans;
y^=ans;
z^=ans;
}
int j=ST(x,y);
int adc=root[s[j]];
int apc=root[t[j]];
if(sum[apc]-sum[adc]<z)
{
ans=-1;
}
else
{
ans=h[query(adc,apc,1,n,sum[apc]-sum[adc]-z+1)];
}
printf("%d\n",ans);
}
}
BZOJ3545&3551[ONTAK2010]Peaks——kruskal重构树+主席树+dfs序+树上倍增的更多相关文章
- 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增
3545: [ONTAK2010]Peaks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1202 Solved: 321[Submit][Sta ...
- 洛谷P4197 Peaks(Kruskal重构树 主席树)
题意 题目链接 往后中文题就不翻译了qwq Sol 又是码农题..出题人这是强行把Kruskal重构树和主席树拼一块了啊.. 首先由于给出的限制条件是<=x,因此我们在最小生成树上走一定是最优的 ...
- 【BZOJ3545】Peaks(Kruskal重构树 主席树)
题目链接 大意 给出有\(N\)个点\(M\)条边的一张图,其中每个点都有一个High值,每条边都有一个Hard值. 再给出\(Q\)个询问:\(v\) \(x\) \(k\) 每次询问查询从点\(v ...
- luogu4197 Peaks (kruskal重构树+主席树)
按照边权排序建出kruskal重构树,每次就变成了先找一个权值<=x的最远的祖先,然后看这个子树的第k小.离散化一下,在dfs序上做主席树即可 而且只需要建叶节点的主席树 注意输出的是第k小点的 ...
- 【BZOJ3551】【BZOJ3545】 【ONTAK2010】 Peaks (kruskal重构树+主席树)
Description 在\(Bytemountains\)有\(~n~\)座山峰,每座山峰有他的高度\(~h_i~\). 有些山峰之间有双向道路相连,共\(~m~\)条路径,每条路径有一个困难值 ...
- [ONTAK2010]Peaks kruskal重构树,主席树
[ONTAK2010]Peaks kruskal重构树练手题. LG传送门竟然不强制在线?看到离线水过很不爽:B站强制在线版传送门 看到"询问从点\(v\)开始只经过困难值小于等于\(x\) ...
- luoguP4197:Peaks(Kruskal重构树+主席树)或者(点分树+离线)
题意:有N座山,M条道路.山有山高,路有困难值(即点权和边权).现在Q次询问,每次给出(v,p),让求从v出发,只能结果边权<=p的边,问能够到达的山中,第K高的高度(从大到小排序). 思路:显 ...
- [IOI2018] werewolf 狼人 [kruskal重构树+主席树]
题意: 当你是人形的时候你只能走 \([L,N-1]\) 的编号的点(即大于等于L的点) 当你是狼形的时候你只能走 \([1,R]\) 的编号的点(即小于等于R的点) 然后问题转化成人形和狼形能到的点 ...
- [BZOJ3551][ONTAK2010]Peaks(加强版)(Kruskal重构树,主席树)
3551: [ONTAK2010]Peaks加强版 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2438 Solved: 763[Submit][ ...
随机推荐
- D. Imbalanced Array
让你计算所有连续子序列的最大值-最小值的和. (单调栈) 对于一个数Ai来讲,如果其有贡献的价值,要么是-Ai作为最小值,要么是Ai作为最大值. 那么Ans=ΣAi*maxn-Ai*minn. voi ...
- 高速LVDS电平简介
一.LVDS简介 1.1.LVDS信号介绍LVDS:Low Voltage Differential Signaling,低电压差分信号.LVDS传输支持速率一般在155Mbps(大约为77MHZ)以 ...
- 2018 Multi-University Training Contest 1 部分简单题解析
Preface ACM系列赛第一站,没有进前200还是很伤的. 主要是T2当时没写出来就GG了,后来看了下其实不是很难. 题目按照比赛时我们A的顺序讲,其实我都是被陈潇然大佬和ZWC带飞的. T1 M ...
- Spring Boot 2.0(七):Spring Boot 如何解决项目启动时初始化资源
在我们实际工作中,总会遇到这样需求,在项目启动的时候需要做一些初始化的操作,比如初始化线程池,提前加载好加密证书等.今天就给大家介绍一个 Spring Boot 神器,专门帮助大家解决项目启动初始化资 ...
- 用PHP山寨一款软件
什么是我国软件工程师引以为豪的能力?山寨.山寨,山寨! 我国程序员的山寨能力是世界一流的.这一点在世界范围内令人闻风丧胆.世界上根本就找不到一款我国工程师不能山寨的软件. 今天,锋哥教大家来山寨一款软 ...
- Docker容器学习梳理 - 基础知识(2)
之前已经总结了Docker容器学习梳理--基础知识(1),但是不够详细,下面再完整补充下Docker学习的一些基础. Docker是个什么东西 Docker是一个程序运行.测试.交付的开放平台,Doc ...
- myeclipse从SVN检出项目报错
今天是在公司实习的第一天,从SVN服务器检出项目后发现报错. 解决方法: 1. 右键项目,选择属性properties-->选择resource-->将others选中并换为UTF-8 2 ...
- python语言几个常见函数的使用
写代码,有如下变量,请按照要求实现每个功能: name = " Kobe Bean Bryant" a. 移除 name 变量对应的值左边的空格,并输出移除后的内容 name = ...
- 阅读<构建之法>10、11、12章
第十章: 典型用户和场景对后面工作有什么帮助吗? 第十一章: 每日构建的目的是什么呢?有没有具体说明? 第十二章: 产品定位人群是否也局限了产品的可拓展性?
- 【软件工程】5.8 黑盒&白盒测试
代码链接:http://www.cnblogs.com/bobbywei/p/4469145.html#3174062 搭档博客:http://www.cnblogs.com/Roc201306114 ...