题目描述

在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强制在线)

样例输入

10 11 4
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

样例输出

6
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序+树上倍增的更多相关文章

  1. 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增

    3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1202  Solved: 321[Submit][Sta ...

  2. 洛谷P4197 Peaks(Kruskal重构树 主席树)

    题意 题目链接 往后中文题就不翻译了qwq Sol 又是码农题..出题人这是强行把Kruskal重构树和主席树拼一块了啊.. 首先由于给出的限制条件是<=x,因此我们在最小生成树上走一定是最优的 ...

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

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

  4. luogu4197 Peaks (kruskal重构树+主席树)

    按照边权排序建出kruskal重构树,每次就变成了先找一个权值<=x的最远的祖先,然后看这个子树的第k小.离散化一下,在dfs序上做主席树即可 而且只需要建叶节点的主席树 注意输出的是第k小点的 ...

  5. 【BZOJ3551】【BZOJ3545】 【ONTAK2010】 Peaks (kruskal重构树+主席树)

    Description ​ 在\(Bytemountains\)有\(~n~\)座山峰,每座山峰有他的高度\(~h_i~\). 有些山峰之间有双向道路相连,共\(~m~\)条路径,每条路径有一个困难值 ...

  6. [ONTAK2010]Peaks kruskal重构树,主席树

    [ONTAK2010]Peaks kruskal重构树练手题. LG传送门竟然不强制在线?看到离线水过很不爽:B站强制在线版传送门 看到"询问从点\(v\)开始只经过困难值小于等于\(x\) ...

  7. luoguP4197:Peaks(Kruskal重构树+主席树)或者(点分树+离线)

    题意:有N座山,M条道路.山有山高,路有困难值(即点权和边权).现在Q次询问,每次给出(v,p),让求从v出发,只能结果边权<=p的边,问能够到达的山中,第K高的高度(从大到小排序). 思路:显 ...

  8. [IOI2018] werewolf 狼人 [kruskal重构树+主席树]

    题意: 当你是人形的时候你只能走 \([L,N-1]\) 的编号的点(即大于等于L的点) 当你是狼形的时候你只能走 \([1,R]\) 的编号的点(即小于等于R的点) 然后问题转化成人形和狼形能到的点 ...

  9. [BZOJ3551][ONTAK2010]Peaks(加强版)(Kruskal重构树,主席树)

    3551: [ONTAK2010]Peaks加强版 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2438  Solved: 763[Submit][ ...

随机推荐

  1. 2-物联网开发标配方案(51单片机程序介绍+WIFI程序介绍)

    上一节  https://www.cnblogs.com/yangfengwu/p/9944438.html 购买云服务器安装MQTT就不用说了,以前写过文章介绍 https://www.cnblog ...

  2. 汇编指令:ldr和str,ldm和stm的区别

    (1)LDR:L表示LOAD,LOAD的含义应该理解为:Load from memory into register.下面这条语句就说明的很清楚: LDR   R1,     [R2] R1<— ...

  3. 【小程序】模拟数据支持(mockjs配置模拟服务器接口数据)

    utils目录 ①下载mockjs(地址)放置utils目录中 ②新建api.js :配置模拟数据以及后台接口,通过DEBUG=ture;  //切换数据接口 配置如下: let API_HOST = ...

  4. LiveCharts文档-3开始-5序列Series

    原文:LiveCharts文档-3开始-5序列Series LiveCharts文档-3开始-5序列Series Strokes和Fills 笔触和填充 所有的Series都有笔触和填充属来处理颜色, ...

  5. phpstorm 2018.1.2的安装和破解

    1.什么是phpstorm? PhpStorm是一个轻量级且便捷的PHP IDE,其旨在提高用户效率,可深刻理解用户的编码,提供智能代码补全,快速导航以及即时错误检查.但是phpstorm是商业软件, ...

  6. NuGet 使用笔记

    环境准备 1. 下载nuget : https://www.nuget.org/downloads 2. 设置到环境变量Path, 使生效:在Cmd打入: set path=abc  关闭Cmd (C ...

  7. NTP系统时间同步-操作记录

    在初始化一台linux服务器后,发现这台服务器的时间不对[root@dev ~]# date2016年 10月 11日 星期二 07:04:34 CST Linux时钟分为系统时钟 (System C ...

  8. 高级程序设计JavaScript

    JavaScript简介 一.因何而生: 方便 表单验证操作(输入验证器) 1995年 2月 Netscape 布兰登 艾奇 JavaScript是一种专门为与网页交互而设计的脚本语言. 二.实现组成 ...

  9. D. Boxes Packing

    链接 [http://codeforces.com/contest/1066/problem/D] 题意 题目大意 n个物品m个篮子每个篮子容量为k 每个物品重量为a[i] 问能装多少物品 这个人是强 ...

  10. Java web错误总结~

    1.java程序中没有错,但是项目上面显示一个红叉的解决办法 错误信息: 报Description  Resource Path Location Type Java compiler level d ...