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][ ...
随机推荐
- EventBus使用详解
EventBus是针一款对Android的发布/订阅事件总线.它可以让我们很轻松的实现在Android各个组件之间传递消息,并且代码的可读性更好,耦合度更低.长话短说直接介绍使用. 如何使用 (以下介 ...
- lesson 4:凯撒密码问题
一·问题描述 二·解决过程 1.设计思路 ①人机交互界面 ②加密函数(将字符串的每一个字符提取出来,通过对字符的阿斯克码值进行运算操作实现加密过程,特殊的特殊对待) ③解密函数(与加密函数算法类似) ...
- 关于window.onload()的加载问题
今天写了个js的demo,遇到了个小问题,后来发现是自己对window.onload()的具体用处不是太清楚,现在跟大家分享一下. <head> <meta http-equiv=& ...
- chrome浏览器直接打印 - z
在地址栏敲: about:flags ,打开设置界面:停用:Enable Print Preview Registration PromosChrome快捷方式增加:--kiosk-printing这 ...
- 51Nod 1677 treecnt
一道比较基础的计数题,还是一个常用的单独计算贡献的例子. 首先看题目和范围,暴力枚举肯定是不可行的,而且\(O(n\ logn)\)的算法貌似很难写. 那我们就来想\(O(n)\)的吧,我们单独考虑每 ...
- [JDBC]ORA-01000: 超出打开游标的最大数(ORA-01000: maximum open cursors exceeded)
问题产生的原因: Java代码在执行conn.createStatement()和conn.prepareStatement()的时候,相当于在数据库中打开了一个cursor.由于oracle对打开的 ...
- 一次Java内存泄漏调试的有趣经历
人人都会犯错,但一些错误是如此的荒谬,我想不通怎么会有人犯这种错误.更没想到的是,这种事竟发生在了我们身上.当然,这种东西只有事后才能发现真相.接下来,我将讲述一系列最近在我们一个应用上犯过的这种错误 ...
- ETL流程介绍及常用实现方法
ETL是英文Extract-Transform-Load 的缩写,用来描述将数据从来源端经过抽取(extract).转换(transform).加载(load)至目的端的过程.常见于数据仓库开发中将数 ...
- Spring Zuul 性能调优,如何提升平均响应时间200% ?
最近负责公司的 Gateway 项目,我们用 Spring Zuul 来做 HTTP 转发,但是发现请求多的时候,AWS 的健康检查就失败了,但是实际上程序还在跑,在日志上也没有任何东西错误打印出来出 ...
- 深入理解USB流量数据包的抓取与分析
0x01 问题提出 在一次演练中,我们通过wireshark抓取了一个如下的数据包,我们如何对其进行分析? 0x02 问题分析 流量包是如何捕获的? 首先我们从上面的数据包分析可以知道,这是个USB的 ...