3545: [ONTAK2010]Peaks

Time Limit: 10 Sec  Memory Limit: 128 MB

Description

在Bytemountains有N座山峰,每座山峰有他的高度h_i。有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1。

Input

第一行三个数N,M,Q。
第二行N个数,第i个数为h_i
接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径。
接下来Q行,每行三个数v x k,表示一组询问。

Output

对于每组询问,输出一个整数表示答案。

Sample Input

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

Sample Output

6
1
-1
8

HINT

【数据范围】

N<=10^5, M,Q<=5*10^5,h_i,c,x<=10^9。

Source

首先一定是走最小生成树上的边是最优的,然后我们按建树的顺序合并节点,这样我们发现一个子树里的边权都小于他本身

然后查询就是倍增找到当前点能到的最远的祖先,就变成了查询子树的第k大,然后用主席树维护就可以了

#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define inf 1000000007
#define ll long long
#define M 6000010
#define N 500010
inline int rd()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,m,Q;
int h[N];
struct qaz{int a,b,c;}e[N],tp[N];
bool cmp(qaz a,qaz b){return a.c<b.c;}
int fa[N],mz;
int findf(int x){return x==fa[x]?x:fa[x]=findf(fa[x]);}
int lj[N],fro[N],to[N],cnt;
void add(int a,int b){fro[++cnt]=lj[a];to[cnt]=b;lj[a]=cnt;}
bool vs[N];
int st[N],ed[N],tim,dep[N];
int Fa[][],rt[N];
int ls[M],rs[M],sz[M],tot;
void add(int lst,int &p,int l,int r,int x)
{
p=++tot;
ls[p]=ls[lst];rs[p]=rs[lst];
sz[p]=sz[lst]+;
if(l==r) return;
int mid=l+r>>;
if(x<=mid) add(ls[lst],ls[p],l,mid,x);
else add(rs[lst],rs[p],mid+,r,x);
}
void dfs(int x)
{
st[x]=++tim;vs[x]=;
dep[x]=dep[Fa[x][]]+;
if(x<=n) add(rt[tim-],rt[tim],,n,h[x]);
else rt[tim]=rt[tim-];
for(int i=;i<;i++)
{
if(dep[x]<(<<i)) break;
Fa[x][i]=Fa[Fa[x][i-]][i-];
}
for(int i=lj[x];i;i=fro[i])
{
Fa[to[i]][]=x;
dfs(to[i]);
}
ed[x]=tim;
}
int fd(int x,int y,int l,int r,int k)
{
if(l==r) return tp[l].c;
int mid=l+r>>;
if(sz[rs[x]]-sz[rs[y]]>=k) return fd(rs[x],rs[y],mid+,r,k);
else return fd(ls[x],ls[y],l,mid,k-sz[rs[x]]+sz[rs[y]]);
}
int main()
{
mz=n=rd();m=rd();Q=rd();
for(int i=;i<=n;i++) tp[i].c=rd(),tp[i].a=i;
sort(tp+,tp+n+,cmp);
for(int i=;i<=n;i++)
{
if(i>&&tp[i].c==tp[i-].c) h[tp[i].a]=h[tp[i-].a];
else h[tp[i].a]=i;
}
for(int i=,a,b,c;i<=m;i++)
{
a=rd();b=rd();c=rd();
e[i]=(qaz){a,b,c};
}
sort(e+,e+m+,cmp);
for(int i=;i<n+n;i++) fa[i]=i;
for(int i=,x,y;i<=m;i++)
{
x=findf(e[i].a);y=findf(e[i].b);
if(x==y) continue;
fa[x]=fa[y]=++mz;
h[mz]=e[i].c;
add(mz,x);add(mz,y);
if(mz==n*-) break;
}
for(int i=;i<=n;i++) if(!vs[i]) dfs(findf(i));
int x,y,z,lans=-,Rt;
while(Q--)
{
x=rd();y=rd();z=rd();
Rt=x;
for(int i=;i>=;i--)
if(dep[Rt]>(<<i)&&h[Fa[Rt][i]]<=y) Rt=Fa[Rt][i];
if(sz[rt[ed[Rt]]]-sz[rt[st[Rt]-]]<z) lans=-;
else lans=fd(rt[ed[Rt]],rt[st[Rt]-],,n,z);
printf("%d\n",lans);
}
return ;
}

bzoj 3545/3551: [ONTAK2010]Peaks -- 主席树,最小生成树,倍增的更多相关文章

  1. bzoj 3545&&3551: [ONTAK2010]Peaks &&加强版 平衡树&&并查集合并树&&主席树

    3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 635  Solved: 177[Submit][Stat ...

  2. BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]

    3551: [ONTAK2010]Peaks加强版 题意:带权图,多组询问与一个点通过边权\(\le lim\)的边连通的点中点权k大值,强制在线 PoPoQQQ大爷题解传送门 说一下感受: 容易发现 ...

  3. 3551: [ONTAK2010]Peaks加强版

    3551: [ONTAK2010]Peaks加强版 https://www.lydsy.com/JudgeOnline/problem.php?id=3551 分析: kruskal重构树 +  倍增 ...

  4. BZOJ_3545_[ONTAK2010]Peaks_主席树+倍增+kruscal重构树+dfs序

    BZOJ_3545_[ONTAK2010]Peaks_主席树+倍增+kruscal重构树 Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道 ...

  5. [BZOJ 2989]数列(二进制分组+主席树)

    [BZOJ 2989]数列(二进制分组+主席树) 题面 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[ ...

  6. 【BZOJ5304】[HAOI2018]字串覆盖(后缀数组,主席树,倍增)

    [BZOJ5304][HAOI2018]字串覆盖(后缀数组,主席树,倍增) 题面 BZOJ 洛谷 题解 贪心的想法是从左往右,能选就选.这个显然是正确的. 题目的数据范围很好的说明了要对于询问分开进行 ...

  7. bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)

    Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来 ...

  8. BZOJ.3551.[ONTAK2010]Peaks加强版(Kruskal重构树 主席树)

    题目链接 \(Description\) 有n个座山,其高度为hi.有m条带权双向边连接某些山.多次询问,每次询问从v出发 只经过边权<=x的边 所能到达的山中,第K高的是多少. 强制在线. \ ...

  9. BZOJ 3551: [ONTAK2010]Peaks加强版 Kruskal重构树+dfs序+主席树+倍增

    建出来 $Kruskal$ 重构树. 将询问点向上跳到深度最小,且合法的节点上. 那么,得益于重构树优美的性质,这个最终跳到的点为根的所有子节点都可以与询问点互达. 对于子树中求点权第 $k$ 大的问 ...

随机推荐

  1. 编译安装 zbar 时两次 make 带来的惊喜

    为了装 php 的条形码扩展模块 php-zbarcode,先装了一天的 ImageMagick 和 zbar.也许和我装的 Ubuntu 17.10 的有版本兼容问题吧,总之什么毛病都有,apt 不 ...

  2. Codechef AMXOR

    Problem Codechef Solution 我们可以按位进行考虑,如果一个 \(m_i\) 在某一位上为1,但 \(x_i\) 却取了0,那么我们就称它脱离了限制,更低位可以随便乱填.也就是说 ...

  3. Java不为人知的小秘密

    Java中的main方法必须有一个外壳类,而且必须是静态的! Java中的所有函数都属于某个类的方法,所以main方法也不例外,必须放在一个类中才能编译运行. 例如: public class tex ...

  4. RabbitMQ--work queues(二)

    封装一个task到一个message,并发送到queue.consumer会去除task并执行这个task. 这里我们简化了操作,发送消息到队列中,consumer取出消息计算里面'.'号有几个就sl ...

  5. 使用os模块实现展示目录下的文件和文件夹

    Windows 10家庭中文版,Python 3.6.4 今天学习了os模块,下面是使用它开发的一个展示目录下的文件和文件夹的函数,代码如下: import os # deep大于等于1的整数,默认为 ...

  6. OpenJDK,Oracle's OpenJDK,Oracle JDK的区别与选择

    OpenJDK 单纯的OpenJDK指的是JDK的源码,以GPL协议开源,由企业和社区开发者共同维护和开发. Oracle's OpenJDK Oracle started providing ope ...

  7. C#实现控制Windows系统关机、重启和注销的方法

    shutdown命令的参数: shutdown.exe -s:关机shutdown.exe -r:关机并重启shutdown.exe -l:注销当前用户 shutdown.exe -s -t 时间:设 ...

  8. IntelliJ IDEA 修改IDE字体、代码字体。

    IntelliJ IDEA 默认的 IDE 菜单字体太小,看着不舒服 ,我们调节下: ==============以上修改 仅仅针对的IDE字体,对代码的字体不生效. 所以如果代码 你觉得小 还得修改 ...

  9. JAVA复习笔记分布式篇:kafka

    前言:第一次使用消息队列是在实在前年的时候,那时候还不了解kafka,用的是阿里的rocket_mq,当时觉得挺好用的,后来听原阿里的同事说rocket_mq是他们看来kafka的源码后自己开发了一套 ...

  10. MySQL学习笔记:删除存储过程和函数

    删除存储过程.存储函数主要使用drop语句: drop procedure  —— 删除存储过程 drop function  —— 删除存储函数 语法: DROP {PROCEDURE|FUNCTI ...