Peaks題解

Peaks題解

這是一道經典的Kruskal重構樹的題目,仍是得好好寫寫,
題目中html

每組詢問詢問從點v開始只通過困難值小於等於x的路徑所能到達的山峯中第k高的山峯c++

ui

從點v開始只通過困難值小於等於x的路徑spa

難以實現
因此咱們要藉助Kruskal重構樹的黑科技,
建一顆Kruskal重構樹,
若有不會的敬請請看這裏
而後每次詢問從一個點往上倍增跳,跳到不能跳爲止
這個點如下的點就是能經過困難值<=x的邊能到達的點,
根據Kruskal重構樹的性質,全部原來節點都在葉子節點,每次查詢這個點所表明的葉子區間中第k大值
k大值,用主席樹維護便可code

#include<bits/stdc++.h>
#define lc son[x][0]
#define rc son[x][1]
using namespace std;
const int N=3e5+6,M=27;
int n,m,Q,tot,cnt=0,num=0,head[N<<1],h[N],f[N<<1],rt[N];
int fa[N<<1][22],maxx[N<<1][22],fst[N<<1],lat[N<<1];
int t1,t2,t3,amt=0,siz,a[N],son[N*20][2],sum[N*20];
struct que{int x,y,z;}q[N];
struct edge{int nxt,to;}e[N<<1];
inline void add(int u,int v){e[++cnt].nxt=head[u],e[cnt].to=v,head[u]=cnt;}
inline int read(){
   int T=0,F=1; char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
   while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
   return F*T;
}
bool cmp(que u,que v){return u.z<v.z;}
int getf(int u){return f[u]==u?u:f[u]=getf(f[u]);}
bool merge(int u,int v,int w){
    u=getf(u),v=getf(v);
    if(u==v) return false;
    ++tot,f[u]=f[v]=f[tot]=tot,add(tot,u),add(tot,v);
    fa[u][0]=fa[v][0]=tot,maxx[u][0]=maxx[v][0]=w;
    return true; 
}
void build(int l,int r,int &x){
    x=++num; int mid=l+r>>1;
    if(l==r) return;
    build(l,mid,lc),build(mid+1,r,rc);
    sum[x]=sum[lc]+sum[rc];
}
void update(int l,int r,int p,int &x,int y){
    if(!x) x=++num;
    sum[x]=sum[y]+1;
    if(l==r) return;
    int mid=l+r>>1;
    if(p<=mid) rc=son[y][1],update(l,mid,p,lc,son[y][0]);
    else lc=son[y][0],update(mid+1,r,p,rc,son[y][1]);
}
int query(int l,int r,int p,int x,int y){
    if(l==r) return l;
    int mid=l+r>>1,o=-sum[rc]+sum[son[y][1]];
    if(p>o) return query(l,mid,p-o,lc,son[y][0]);
    else return query(mid+1,r,p,rc,son[y][1]);
}
void dfs(int x){
    for(int i=1;i<=20;++i) fa[x][i]=fa[fa[x][i-1]][i-1],maxx[x][i]=max(maxx[x][i-1],maxx[fa[x][i-1]][i-1]);
    fst[x]=amt;
    if(!head[x]) ++amt,fst[x]=amt,t1=lower_bound(a+1,a+siz+1,h[x])-a,update(1,siz,t1,rt[amt],rt[amt-1]);
    for(int i=head[x];i;i=e[i].nxt) dfs(e[i].to);
    lat[x]=amt;
}
int main(){
    n=read(),m=read(),Q=read(),tot=n;
    for(int i=1;i<=n;++i) h[i]=read(),f[i]=i,a[i]=h[i];
    for(int i=1;i<=m;++i) q[i].x=read(),q[i].y=read(),q[i].z=read();
    sort(q+1,q+m+1,cmp),sort(a+1,a+n+1),siz=unique(a+1,a+n+1)-a-1;
    for(int i=1;i<n;++i){
        ++num;
        if(num>m) break;
        if(!merge(q[num].x,q[num].y,q[num].z)) --i;
    }
    num=0,build(1,siz,rt[0]),dfs(tot);
    for(int i=1;i<=Q;++i){
        t1=read(),t2=read(),t3=read();
        for(int j=20;j>=0;--j) if(fa[t1][j]&&t2>=maxx[t1][j]) t1=fa[t1][j];
        if(sum[rt[lat[t1]]]-sum[rt[fst[t1]]]<t3) printf("-1\n");
        else printf("%d\n",a[query(1,siz,t3,rt[fst[t1]],rt[lat[t1]])]); 
    }
    return 0;
}
相關文章
相關標籤/搜索