Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1124  Solved: 304
[Submit][Status][Discuss]

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。

题解:

  把M+Q个操作全部存起来,准备离线操作,添加路径的flag为1,询问的flag为0,id为i-M方便记录答案。以困难值为第一关键字,flag为第二关键字排序。这样碰到询问操作则当前的的所有连通块之间的边的困难值满足要求,记录连通块之间的信息用并查集维护一下就好了。

  本题用可持久化线段树的来维护,建立N棵线段树,如果a和b之间连了一条边,则把线段树a和线段树b合并起来,由于所有线段树的形态均相同,所以只要对应的权值相加减即可。

  具体看代码。

 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int maxn=1e5+;
inline int read(){
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,ans[*maxn];
int H[maxn],h[maxn],hash[maxn],tot;
int root[maxn],siz;
struct Tree{
int lc,rc,w;
}tr[maxn*];
inline int find(int x){
int l=,r=tot;
while(l<=r){
int mid=(l+r)>>;
if(hash[mid]<x) l=mid+;
else if(hash[mid]>x) r=mid-;
else if(hash[mid]==x) return mid;
}
return l;
} struct node{
int a,b,w;
int flag,id;
}g[maxn*];
int cmp(const node&q,const node&e){
return q.w<e.w||(q.w==e.w&&q.flag>e.flag);
} int fa[maxn];
inline int getfa(int r){
if(r!=fa[r]) fa[r]=getfa(fa[r]);
return fa[r];
} inline void insert(int &i,int l,int r,int w){
i=++siz;
tr[i].w=;
if(l==r) return ;
int mid=(l+r)>>;
if(w<=mid) insert(tr[i].lc,l,mid,w);
else insert(tr[i].rc,mid+,r,w);
}
inline int query(int i,int l,int r,int k){
if(l==r) return l;
int mid=(l+r)>>;
if(tr[tr[i].lc].w>=k)return query(tr[i].lc,l,mid,k);
else return query(tr[i].rc,mid+,r,k-tr[tr[i].lc].w);
}
inline int merge(int x,int y){
if(x==) return y;
if(y==) return x;
if(tr[x].lc==&&tr[x].rc==){
tr[x].w=tr[x].w+tr[y].w;
return x;
}
tr[x].lc=merge(tr[x].lc,tr[y].lc);
tr[x].rc=merge(tr[x].rc,tr[y].rc);
tr[x].w=tr[tr[x].lc].w+tr[tr[x].rc].w;
return x;
}
int main(){
N=read(); M=read(); Q=read();
for(int i=;i<=N;i++) H[i]=read(),h[i]=H[i];
sort(h+,h+N+);
hash[++tot]=h[];
for(int i=;i<=N;i++){//按照山的高度离散化+去重
if(h[i]!=h[i-]) hash[++tot]=h[i];
} for(int i=,a,b,w;i<=M+Q;i++){
a=read(); b=read(); w=read();
if(i<=M){
g[i].flag=;
g[i].a=a; g[i].b=b; g[i].w=w;
}
else{
g[i].id=i-M;
g[i].a=a; g[i].w=b; g[i].b=w;
}
}
sort(g+,g+M+Q+,cmp);
for(int i=;i<=N;i++) fa[i]=i;
for(int i=;i<=N;i++){
int w=find(H[i]);
insert(root[i],,tot,w);
}
for(int i=;i<=M+Q;i++){
if(g[i].flag==){//在图中加入一条边
int p=getfa(g[i].a),q=getfa(g[i].b);
if(p!=q){
fa[p]=q;
root[q]=merge(root[p],root[q]);
}
}
else{//询问
int v=getfa(g[i].a);
if(tr[root[v]].w<g[i].b) ans[g[i].id]=-;
else ans[g[i].id]=hash[query(root[v],,tot,tr[root[v]].w-g[i].b+)];
}
}
for(int i=;i<=Q;i++){
printf("%d\n",ans[i]);
}
return ;
}

bzoj 3545: [ONTAK2010]Peaks的更多相关文章

  1. BZOJ 3545: [ONTAK2010]Peaks( BST + 启发式合并 + 并查集 )

    这道题很好想, 离线, 按询问的x排序从小到大, 然后用并查集维护连通性, 用平衡树维护连通块的山的权值, 合并就用启发式合并.时间复杂度的话, 排序是O(mlogm + qlogq), 启发式合并是 ...

  2. BZOJ 3545: [ONTAK2010]Peaks [Splay启发式合并]

    3545: [ONTAK2010]Peaks 题意:带权图,多组询问与一个点通过边权\(\le x\)的边连通的点中点权k大值 又读错题了,输出点一直WA,问的是点权啊 本题加强版强制在线了,那这道题 ...

  3. ●BZOJ 3545 [ONTAK2010]Peaks(离线)

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3545 http://www.lydsy.com/JudgeOnline/problem.ph ...

  4. BZOJ.3545.[ONTAK2010]Peaks(线段树合并)

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

  5. bzoj 3545: [ONTAK2010]Peaks Kruskal重构树

    题目: 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经 ...

  6. BZOJ 3545: [ONTAK2010]Peaks 启发式合并 + 离线 + Splay

    Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询 ...

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

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

  8. BZOJ 3551/3545: [ONTAK2010]Peaks加强版 (Kruskal树+dfs序上的主席树+倍增)

    Orz PoPoQQQ 学到了维护子树信息的时候用dfsdfsdfs序套主席树节省线段树空间. 学到了怎么用指针写可持久化线段树-emmm- CODE 只贴上3551加强版带强制在线的代码 #incl ...

  9. bzoj 3551: [ONTAK2010]Peaks加强版

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

随机推荐

  1. HDU2842—Chinese Rings

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2842 题目意思:一把一个n连环的前n个拿下来,一个个n连环,要把第k个拿下来,需要把前n-2个拿下来, ...

  2. 【Python之路】Python目录

    Python基础1 -- Python由来.Python种类.编码方式, Python基础2 -- Python运算符.数据类型.enumerate.range.for循环 python基础3 -- ...

  3. HTML 之轮播图

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. 汉诺塔IV---hdu2077

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2077 #include <stdio.h> #include <stdlib.h&g ...

  5. Loki之ThreadPool

    Loki中的ThreadPool目的主要是对创建出来的线程进行复用. ThreadPool在Test而非Loki目录下,因此并非是标准Loki的组件之一,不过我们可以对其修改定制, 下面是对其源码的大 ...

  6. python 字符串的格式化

    python字符串的格式化分为两种:1)% 方式    2)str.format()  方式. str.format() 是比 % 较新的方式, 大多数的 Python 代码仍然使用 % 操作符.但最 ...

  7. PHP计算经纬度之间的距离

    <?php /** * 求两个已知经纬度之间的距离,单位为米 * * @param lng1 $ ,lng2 经度 * @param lat1 $ ,lat2 纬度 * @return floa ...

  8. centos7部署PaaS平台环境(mesos+marathon)

    假如有5台主机可以使用,ip地址如下 规划(2master+3slave) master: 192.168.248.205 ---master1 192.168.248.206 ---master2 ...

  9. PAT 1033 To Fill or Not to Fill[dp]

    1033 To Fill or Not to Fill(25 分) With highways available, driving a car from Hangzhou to any other ...

  10. MySQL · 引擎特性 · InnoDB redo log漫游(转)

    前言 InnoDB 有两块非常重要的日志,一个是undo log,另外一个是redo log,前者用来保证事务的原子性以及InnoDB的MVCC,后者用来保证事务的持久性. 和大多数关系型数据库一样, ...