【BZOJ3551】Peaks加強版(Kruskal重構樹,主席樹)
阿新 • • 發佈:2018-09-01
www top return ostream https zoj 高度 ble lib
【BZOJ3551】Peaks加強版(Kruskal重構樹,主席樹)
題面
BZOJ
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。
題解
很明顯的克魯斯卡爾重構樹之後直接用主席樹維護區間第\(K\)大。
註意克魯斯卡爾重構樹維護的最小生成樹的邊權是放在點上的。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<vector> using namespace std; #define ll long long #define MAX 200500 inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } struct Line{int v,next;}e[MAX]; int h[MAX],cnt=1; inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;} struct edge{int u,v,w;}E[MAX<<2]; bool operator<(edge a,edge b){return a.w<b.w;} int f[MAX],tot; int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);} int n,m,Q,a[MAX]; int p[20][MAX],dis[MAX]; int dfn[MAX],low[MAX],ln[MAX],tim; void dfs(int u,int ff) { if(u<=n)dfn[u]=low[u]=++tim,ln[tim]=u; else dfn[u]=1e9,low[u]=0; p[0][u]=ff; for(int i=1;i<20;++i)p[i][u]=p[i-1][p[i-1][u]]; for(int i=h[u];i;i=e[i].next) dfs(e[i].v,u),dfn[u]=min(dfn[u],dfn[e[i].v]),low[u]=max(low[u],low[e[i].v]); } int rt[MAX],S[MAX],top; struct Node{int ls,rs,v;}t[MAX*20]; int num; void modify(int &x,int l,int r,int p) { t[++num]=t[x];++t[x=num].v;if(l==r)return; int mid=(l+r)>>1; if(p<=mid)modify(t[x].ls,l,mid,p); else modify(t[x].rs,mid+1,r,p); } int Query(int A,int B,int l,int r,int K) { if(l==r)return S[l]; int mid=(l+r)>>1,sum=t[t[A].rs].v-t[t[B].rs].v; if(sum>=K)return Query(t[A].rs,t[B].rs,mid+1,r,K); else return Query(t[A].ls,t[B].ls,l,mid,K-sum); } int main() { n=read();m=read();Q=read(); for(int i=1;i<=n;++i)S[i]=a[i]=read(); sort(&S[1],&S[n+1]);top=unique(&S[1],&S[n+1])-S-1; for(int i=1;i<=n;++i)a[i]=lower_bound(&S[1],&S[top+1],a[i])-S; for(int i=1;i<=m;++i) { int u=read(),v=read(),w=read(); E[i]=(edge){u,v,w}; } sort(&E[1],&E[m+1]); for(int i=1;i<=n;++i)f[i]=i;tot=n; for(int i=1;i<=m;++i) { int u=getf(E[i].u),v=getf(E[i].v); if(u==v)continue;++tot; f[tot]=f[u]=f[v]=tot;dis[tot]=E[i].w; Add(tot,u);Add(tot,v); } dfs(tot,0); for(int i=1;i<=n;++i)modify(rt[i]=rt[i-1],1,top,a[ln[i]]); int lans=0; while(Q--) { int v=read(),x=read(),K=read(); if(lans!=-1)v^=lans,x^=lans,K^=lans; for(int i=19;~i;--i) if(p[i][v]&&dis[p[i][v]]<=x) v=p[i][v]; if(low[v]-dfn[v]+1<K)lans=-1; else lans=Query(rt[low[v]],rt[dfn[v]-1],1,top,K); printf("%d\n",lans); } return 0; }
【BZOJ3551】Peaks加強版(Kruskal重構樹,主席樹)