【bzoj3545】[ONTAK2010]Peaks 线段树合并
【bzoj3545】[ONTAK2010]Peaks
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
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
1
-1
8
HINT
【数据范围】
N<=10^5, M,Q<=5*10^5,h_i,c,x<=10^9。
题解
离散后排序,维护加边顺序,然后就是线段树合并了,权值线段树。
1 #include<cstring> 2 #include<cmath> 3 #include<algorithm> 4 #include<iostream> 5 #include<cstdio> 6 7 #define N 100007 8 #define M 500007 9 #define ll long long 10 using namespace std; 11 inline int read() 12 { 13 int x=0,f=1;char ch=getchar(); 14 while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();} 15 while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} 16 return x*f; 17 } 18 19 int n,m,q,sz; 20 int fa[N],rt[N],ans[M],disc[N],h[N]; 21 int siz[M*10],ls[M*10],rs[M*10]; 22 struct Node 23 { 24 int x,y,difficulty; 25 }a[M]; 26 struct Date 27 { 28 int x,limit,k,id; 29 }b[M]; 30 31 int find(int num) 32 { 33 if (fa[num]!=num) fa[num]=find(fa[num]); 34 return fa[num]; 35 } 36 bool cmp(Node x,Node y) 37 { 38 return x.difficulty<y.difficulty; 39 } 40 bool cmp1(Date x,Date y) 41 { 42 return x.limit<y.limit; 43 } 44 45 int merge(int x,int y) 46 { 47 if (!x)return y; 48 if (!y)return x; 49 if (!ls[x]&&!rs[x]) 50 { 51 siz[x]=siz[x]+siz[y]; 52 return x; 53 } 54 ls[x]=merge(ls[x],ls[y]); 55 rs[x]=merge(rs[x],rs[y]); 56 siz[x]=siz[ls[x]]+siz[rs[x]]; 57 return x; 58 } 59 void ins(int &p,int l,int r,int z) 60 { 61 if (!p)p=++sz,siz[p]=1; 62 if (l==r) return; 63 int mid=(l+r)>>1; 64 if (z<=mid)ins(ls[p],l,mid,z); 65 else ins(rs[p],mid+1,r,z); 66 } 67 int query(int p,int l,int r,int rank) 68 { 69 if (l==r) return l; 70 int mid=(l+r)>>1; 71 if (rank<=siz[ls[p]])return query(ls[p],l,mid,rank); 72 else return query(rs[p],mid+1,r,rank-siz[ls[p]]); 73 } 74 void solve() 75 { 76 int now=0; 77 for (int i=1;i<=q;i++) 78 { 79 while(now<m&&a[now+1].difficulty<=b[i].limit) 80 { 81 int x=find(a[now+1].x),y=find(a[now+1].y); 82 if (x!=y) 83 { 84 fa[y]=x; 85 rt[x]=merge(rt[x],rt[y]); 86 } 87 now++; 88 } 89 int x=find(b[i].x); 90 if (siz[rt[x]]<b[i].k) ans[b[i].id]=-1; 91 else ans[b[i].id]=disc[query(rt[x],1,n,siz[rt[x]]-b[i].k+1)]; 92 } 93 for (int i=1;i<=q;i++) 94 printf("%d\n",ans[i]); 95 } 96 int main() 97 { 98 freopen("fzy.in","r",stdin); 99 freopen("fzy.out","w",stdout); 100 101 n=read(),m=read(),q=read(); 102 for (int i=1;i<=n;i++) 103 disc[i]=h[i]=read(),fa[i]=i; 104 sort(disc+1,disc+n+1); 105 for (int i=1;i<=n;i++) 106 h[i]=lower_bound(disc+1,disc+n+1,h[i])-disc; 107 for (int i=1;i<=n;i++) 108 ins(rt[i],1,n,h[i]); 109 110 for (int i=1;i<=m;i++) 111 a[i].x=read(),a[i].y=read(),a[i].difficulty=read(); 112 sort(a+1,a+m+1,cmp); 113 for (int i=1;i<=q;i++) 114 b[i].x=read(),b[i].limit=read(),b[i].k=read(),b[i].id=i; 115 sort(b+1,b+q+1,cmp1); 116 solve(); 117 }