bzoj 3545: [ONTAK2010]Peaks (splay启发式合并)

来源:互联网 发布:淘宝天猫摇一摇在哪里 编辑:程序博客网 时间:2024/05/16 08:05

3545: [ONTAK2010]Peaks

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1750  Solved: 472
[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

By Sbullet



明明记得这题放过题解,找不到了,那就再放一次。。。


对于每个并查集开一颗splay,合并并查集的同时启发式合并splay


启发式合并是什么意思呢,小的splay暴力插入大的中.......


代码:

#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<algorithm>#include<cstring>#include<string>#include<climits>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#define N 500010#define M 2500010using namespace std;inline int read(){int x=0,f=1;char ch;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 n,m,q,ans[N];int tr[M][2],fa[M],size[M];int root[N],v[M],sz;inline void pushup(int k){size[k]=size[tr[k][0]]+size[tr[k][1]]+1;}inline void rotate(int x,int &k){int y=fa[x],z=fa[y],l,r;l=tr[y][1]==x;r=l^1;if(k==y)k=x;else tr[z][tr[z][1]==y]=x;fa[x]=z,fa[y]=x,fa[tr[x][r]]=y;tr[y][l]=tr[x][r],tr[x][r]=y;pushup(y);pushup(x);}inline void splay(int x,int &k){while(x!=k){int y=fa[x],z=fa[y];if(y!=k){if(tr[y][0]==x^tr[z][0]==y)rotate(x,k);else rotate(y,k);}rotate(x,k);}}inline int find_k(int k,int rk){int l=tr[k][0],r=tr[k][1];if(size[r]+1==rk)return v[k];else if(size[r]>=rk)return find_k(r,rk);else return find_k(l,rk-size[r]-1);}int t1,t2;inline void ins(int &k,int x,int last,int &rt){if(!k){k=++sz;fa[k]=last,size[k]=1,v[k]=x;splay(k,rt);return;}else if(v[k]>=x)ins(tr[k][0],x,k,rt);else ins(tr[k][1],x,k,rt);}inline void merge(int k,int &rt){if(!k)return;merge(tr[k][0],rt);merge(tr[k][1],rt);ins(rt,v[k],0,rt);}int pre[N],h[N];int find(int x){return x==pre[x]?x:pre[x]=find(pre[x]);} inline void work(int a,int b){int rb=root[b],ra=root[a];if(size[root[b]]>size[root[a]]) swap(a,b);pre[b]=a;merge(root[b],root[a]);}struct edge{int x,y,c;}e[M];bool operator < (edge a,edge b){return a.c<b.c;}struct qry{int v,x,k,id;}ak[M]; bool operator < (qry a,qry b){return a.x<b.x;}void init(){n=read(),m=read(),q=read();for(int i=1;i<=n;i++)h[i]=read();for(int i=1;i<=n;i++){pre[i]=i;ins(root[i],h[i],0,i);}for(int i=1;i<=m;i++){e[i].x=read();e[i].y=read();e[i].c=read();}sort(e+1,e+1+m);for(int i=1;i<=q;i++){ak[i].v=read();ak[i].x=read();ak[i].k=read();ak[i].id=i;}sort(ak+1,ak+1+q);}int main(){//freopen("in.txt","r",stdin);//freopen("my.txt","w",stdout);init();int i=0,j=1;for(i=1;i<=q;i++){while(e[j].c<=ak[i].x&&j<=m){int a=e[j].x,b=e[j].y;int fa=find(a),fb=find(b);if(fa!=fb)work(fa,fb);j++;}int t=find(ak[i].v);if(size[root[t]]<ak[i].k)ans[ak[i].id]=-1;else ans[ak[i].id]=find_k(root[t],ak[i].k);}for(int i=1;i<=q;i++)printf("%d\n",ans[i]);}



0 0
原创粉丝点击