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. APUE-文件和目录(八)文件时间

    文件的时间 与文件相关的三个时间值: 访问时间:最后一次访问文件的时间.例如,cat命令会修改这个时间. 修改时间:文件内容最后一次被修改的时间. 状态更改时间:文件的i节点最后一次被修改的时间.例如 ...

  2. Unity教程之-Unity3d中针对Android Apk的签名验证(C#实现)

    当Unity开发的游戏以Android Apk的形式发布之后,经常会遇到的一种情况就是别人对我们的游戏进行二次打包,也就是用他们的签名替换掉我们的签名,从而堂而皇之的将胜利果实占为己有.面对这样的情况 ...

  3. Flask:abort()函数

    Windows 10家庭中文版,Python 3.6.4,Flask 1.0.2 abort()函数用于提前退出(Google翻译abort)一个请求,并用指定的错误码返回. 函数原型如下: flas ...

  4. 签名DLL

    签名DLL 首先需要一个密钥文件,后缀为.snk 密钥文件使用sn.exe 创建: sn.exe /k MySingInKey.snk  sn.exe 工具的具体使用,可以通过 sn.exe /h 或 ...

  5. KVM和远程管理工具virt-manager

    kvm在server端的部署(针对rhel6系统,可以构建本地更新源) 注意:如果只是安装管理工具,可以试试直接执行8步骤 1.对服务器实行kvm虚拟化首先需要确认服务器的物理硬件是否支持 cat / ...

  6. POJ 2186 Popular Cows(强联通分量)

    题目链接:http://poj.org/problem?id=2186 题目大意:    每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎. 这 种 ...

  7. Unix IPC之pipe

    pipe创建函数: #include <unistd.h> /* Create a one-way communication channel (pipe). If successful, ...

  8. Java事务管理之JDBC

    前言 关于Java中JDBC的一些使用可以参见: Java 中使用JDBC连接数据库例程与注意事项 在使用JDBC的使用, 如何进行事务的管理.直接看一下代码 示例代码 /** * @Title: J ...

  9. Oracle 提示符

    http://blog.csdn.net/wyzxg/article/details/5647905

  10. phpmyadmin新加用户登陆不了,测试解决方案。

    今天在给项目配置数据库管理平台时遇到一个问题,不论怎么添加mysql用户在登陆phpmyadmin时始终无法登陆,不管准不准许为空依然报出#1045 无法登陆服务器的错误,最后打开mysql库中use ...