zoukankan      html  css  js  c++  java
  • 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
    ",lasans);
        }
        return 0;
    }
    Peaks
  • 相关阅读:
    Flink基于EventTime和WaterMark处理乱序事件和晚到的数据
    flink 有什么优点
    Flink-Kafka 连接器及exactly-once 语义保证
    腾讯大学
    Qt 获取文件路径、文件名、后缀
    Qt QDir::currentPath()和QAppllication::appllicationDirPath()用法区别
    Qt 程序获取程序所在路径、用户目录路径、临时文件夹等特殊路径的方法
    Qt comboBox设置下拉菜单()
    Qt 快速读写Excel指南
    可见光的波长与频率对照表
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14639130.html
Copyright © 2011-2022 走看看