1. 程式人生 > >【bzoj3545】[ONTAK2010]Peaks 線段樹合並

【bzoj3545】[ONTAK2010]Peaks 線段樹合並

peak spa names 順序 query algorithm com ring led

【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

Sample Output

6
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 }

【bzoj3545】[ONTAK2010]Peaks 線段樹合並