[bzoj3445][ONTAK2010]Peaks 离线+线段树合并

来源:互联网 发布:办公软件合集 编辑:程序博客网 时间:2024/06/06 00:01

3545: [ONTAK2010]Peaks

Time Limit: 10 Sec  Memory Limit: 128 MB[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。

Source

需离散化
卡时卡空间过
#include<algorithm>#include<iostream>#include<cstdlib>#include<cstdio>using namespace std;const int N = 5000005;const int M = 100005;int n,m,q,id;int hh[100005],fa[100005],h[100005],root[100005],ans[500005];struct data{int a,k,b,x,ans,id,f;}a[1000005];int ls[5000005],rs[5000005],sum[5000005];bool cmp( data a, data b ){ return a.x < b.x || (a.x==b.x&&a.f<b.f); }int find( int x ){ return fa[x] == x ? x : fa[x] = find(fa[x]); }void build( int &k, int l, int r, int val ){if(!k) k = ++id; sum[k] = 1;if( l == r ) return ; int mid = (l+r)>>1;if( mid >= val ) build( ls[k], l, mid, val );else build( rs[k], mid+1, r, val );}int merge( int x, int y ){if( !x || !y ) return x+y;if( !ls[x] && !rs[x] ){sum[x] = sum[x] + sum[y]; return x;}ls[x] = merge(ls[x],ls[y]); rs[x] = merge(rs[x],rs[y]);sum[x] = sum[ls[x]] + sum[rs[x]];return x;}int query( int k, int l, int r, int val ){if( l == r ) return l;int mid = (l+r)>>1;if( sum[ls[k]] >= val ) return query(ls[k],l,mid,val);else return query(rs[k],mid+1,r,val-sum[ls[k]]);}inline const int read(){    register int f=1,x=0;    register char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}    return f*x;}int main(){scanf("%d%d%d", &n, &m, &q);for( int i = 1; i <= n; i++ ) h[i]=read(), hh[i] = h[i], fa[i] = i;std::sort(hh+1,hh+n+1);for( int i = 1; i <= n; i++ ) h[i] = lower_bound(hh+1,hh+n+1,h[i]) - hh;for( int i = 1; i <= m; i++ ) a[i].a=read(),a[i].b=read(),a[i].x=read(),a[i].f=0;for( int i = 1+m; i <= q+m; i++ ) a[i].a=read(),a[i].x=read(),a[i].k=read(),a[i].id=i-m,a[i].f=1;std::sort(a+1,a+q+m+1,cmp);for( int i = 1; i <= n; i++ ) build( root[i], 1, n, h[i] );for( int i = 1; i <= m+q; i++ )if( !a[i].f ){int p = find(a[i].a), Q = find(a[i].b);if( p != Q ){fa[p] = Q;root[Q] = merge(root[p],root[Q]);}} else{int p = find(a[i].a);if( sum[root[p]] < a[i].k ) ans[a[i].id] = -1;else ans[a[i].id] = hh[query(root[p],1,n,sum[root[p]]-a[i].k+1)];}for( int i = 1; i <= q; i++ ) printf("%d\n",ans[i]);return 0;}


阅读全文
0 0
原创粉丝点击