LG P4197 Peaks/BZOJ3551 [ONTAK2010]Peaks加强版

Description

在 Bytemountains 有 $n$ 座山峰,每座山峰有他的高度 $h_i$。有些山峰之间有双向道路相连,共 $m$ 条路径,每条路径有一个困难值,这个值越大表示越难走。

现在有 $q$ 组询问,每组询问询问从点 $v$ 开始只经过困难值小于等于 $x$ 的路径所能到达的山峰中第 $k$ 高的山峰,如果无解输出 $-1$。

Solution

kruskal重构树后,由点$x$可以到达的,经过边权小于$k$的构成一个包含$x$的子树,可以倍增找到子树的根

转化为一个子树内的第$k$大,可以再转化到DFS序上区间第$k$大

主席树干就完了

两个题的区别在于是否强制在线

#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
int n,m,q,val[200005],sav[200005],N,f[200005],head[200005],tot,fa[200005][21],in[200005],out[200005],idx,lasans;
bool vst[200005];
struct Node{
    int x,y,w;
    bool operator <(const Node &z)const{return w<z.w;}
}node[500005];
struct Edge{
    int to,nxt;
}edge[500005];
namespace SGT{
    int cnt,rt[200005],ls[4000005],rs[4000005],sum[4000005];
    int update(int i,int l,int r,int p){
        int k=++cnt,mid=l+r>>1;
        ls[k]=ls[i],rs[k]=rs[i],sum[k]=sum[i]+1;
        if(l==r)return k;
        if(p<=mid)ls[k]=update(ls[i],l,mid,p);
        else rs[k]=update(rs[i],mid+1,r,p);
        return k;
    }
    int query(int u,int v,int l,int r,int k){
        if(l==r)return l;
        int mid=l+r>>1,s=sum[rs[v]]-sum[rs[u]];
        if(s>=k)return query(rs[u],rs[v],mid+1,r,k);
        else return query(ls[u],ls[v],l,mid,k-s);
    }
}
inline int read(){
    int f=1,w=0;
    char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
    return f*w;
}
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
void addedge(int u,int v){edge[++tot]=(Edge){v,head[u]},head[u]=tot;}
void Exkruskal(){
    int cnt=n;
    sort(node+1,node+m+1);
    for(int i=1;i<=m;i++){
        int fx=find(node[i].x),fy=find(node[i].y);
        if(fx!=fy){
            val[++cnt]=node[i].w,f[fx]=cnt,f[fy]=cnt,addedge(cnt,fx),addedge(cnt,fy);
            if(cnt==2*n-1)break;
        }
    }
}
void dfs(int k,int f){
    fa[k][0]=f,in[k]=++idx,vst[k]=true;
    for(int i=1;i<=20;i++)fa[k][i]=fa[fa[k][i-1]][i-1];
    if(k<=n)SGT::rt[idx]=SGT::update(SGT::rt[idx-1],1,N,val[k]);
    else SGT::rt[idx]=SGT::rt[idx-1];
    for(int i=head[k];i;i=edge[i].nxt){
        int v=edge[i].to;
        dfs(v,k);
    }
    out[k]=idx;
}
int findpos(int x,int lim){
    for(int i=20;~i;i--)if(val[fa[x][i]]<=lim)x=fa[x][i];
    return x;
}
int main(){
    n=read(),m=read(),q=read(),val[0]=0x7f7f7f7f;
    for(int i=1;i<=n;i++)sav[i]=val[i]=read();
    sort(sav+1,sav+n+1),N=unique(sav+1,sav+n+1)-sav-1;
    for(int i=1;i<=n;i++)val[i]=lower_bound(sav+1,sav+N+1,val[i])-sav;
    for(int i=1;i<=m;i++)node[i]=(Node){read(),read(),read()};
    for(int i=1;i<=2*n;i++)f[i]=i;
    Exkruskal();
    for(int i=1;i<=n;i++)if(!vst[i])dfs(find(i),0);
//    for(int i=1;i<=n*2-1;i++)cout<<fa[i][2]<<" ";
    for(;q;q--){
        int v=read(),x=read(),k=read();
        int pos=findpos(v,x);
//        cout<<SGT::sum[SGT::rt[out[pos]]]<<" ";
        if(SGT::sum[SGT::rt[out[pos]]]-SGT::sum[SGT::rt[in[pos]-1]]<k)lasans=-1;
        else lasans=sav[SGT::query(SGT::rt[in[pos]-1],SGT::rt[out[pos]],1,N,k)];
        printf("%d\n",lasans);
    }
    return 0;
}
Peaks

 

posted @ 2021-04-10 18:08  QDK_Storm  阅读(48)  评论(0编辑  收藏  举报