#Kruskal重构树,主席树,倍增#洛谷 4197 Peaks

题目传送门


分析

首先第\(k\)大一般都是主席树
问题是困难值的限制有点束手无措
又是\(\text{Kruskal重构树}\)
将困难值为边权跑最小生成树,重新建树,实际上让困难值跳到尽量大的位置就可以了,那可以倍增实现
然后找到这个点,实际可以按照dfs序代表一个区间,那么可以转换为区间求解


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int N=100011;
struct Chair{
    int w[N<<5],ls[N<<5],rs[N<<5],cnt;
    inline void build(int &rt,int l,int r){
        w[rt=++cnt]=0; rr int mid=(l+r)>>1;
        if (l<r) build(ls[rt],l,mid),build(rs[rt],mid+1,r); 
    }
    inline void update(int &rt,int l,int r,int k){
        rr int trt=++cnt,mid=(l+r)>>1;
        ls[trt]=ls[rt],rs[trt]=rs[rt],w[trt]=w[rt]+1,rt=trt;
        if (l==r) return;
        k<=mid?update(ls[trt],l,mid,k):update(rs[trt],mid+1,r,k);
    }
    inline signed query(int L,int R,int l,int r,int k){
        if (l==r) return l;
        rr int x=w[rs[R]]-w[rs[L]],mid=(l+r)>>1;
        return x<k?query(ls[L],ls[R],l,mid,k-x):query(rs[L],rs[R],mid+1,r,k);
    }
}Tre;
struct node{int y,next;}e[N<<1]; struct rec{int x,y,w;}T[N*5];
int d[N<<1],ls[N<<1],fat[N<<1],f[N<<1][18],lfn[N<<1],rfn[N<<1];
int Dfn,n,k=1,m,Q,sn,dep[N<<1],rt[N],h[N],b[N],tot;
inline signed iut(){
    rr int ans=0; rr char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    return ans;
}
inline void print(int ans){
    if (ans>9) print(ans/10);
    putchar(ans%10+48);
}
bool cmp(rec x,rec y){return x.w<y.w;}
inline void add(int x,int y){e[++k]=(node){y,ls[x]},ls[x]=k;}
inline signed getf(int u){return fat[u]==u?u:fat[u]=getf(fat[u]);}
inline void Kruskal(){
    for (rr int i=1;i<n*2;++i) fat[i]=i;
    for (rr int i=1,tOt=0;i<=m;++i){
        rr int fa=getf(T[i].x),fb=getf(T[i].y);
        if (fa!=fb){
            fat[fa]=fat[fb]=++sn,d[sn]=T[i].w;
            add(sn,fa),add(sn,fb);
            if (++tOt==n-1) return;
        }
    }
}
inline void dfs(int x,int fa){
    f[x][0]=fa,lfn[x]=Dfn,dep[x]=dep[fa]+1;
    for (rr int i=1;i<18;++i)
        f[x][i]=f[f[x][i-1]][i-1];
    if (!ls[x]){
        lfn[x]=++Dfn;
        Tre.update(rt[Dfn]=rt[Dfn-1],1,tot,h[x]);
    }
    for (rr int i=ls[x];i;i=e[i].next) dfs(e[i].y,x);
    rfn[x]=Dfn;
}
signed main(){
    Tre.cnt=0,sn=n=iut(),m=iut(),Q=iut();
    for (rr int i=1;i<=n;++i) h[i]=b[i]=iut();
    sort(b+1,b+1+n),tot=unique(b+1,b+1+n)-b-1;
    for (rr int i=1;i<=n;++i) h[i]=lower_bound(b+1,b+1+tot,h[i])-b;
    for (rr int i=1;i<=m;++i) T[i]=(rec){iut(),iut(),iut()};
    sort(T+1,T+1+m,cmp),Kruskal(),Tre.build(rt[0],1,tot),dfs(sn,0);
    while (Q--){
        rr int x=iut(),D=iut(),Kth=iut();
        for (rr int i=17;~i;--i) if (f[x][i]&&d[f[x][i]]<=D) x=f[x][i];
        if (rfn[x]-lfn[x]<Kth) putchar('-'),putchar(49),putchar(10);
            else print(b[Tre.query(rt[lfn[x]],rt[rfn[x]],1,tot,Kth)]),putchar(10);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Spare-No-Effort/p/12355247.html