• [BZOJ3545]Peaks


    题目大意:
    有N座山峰,每座山峰有他的高度(h_i)。有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1。
    解题思路:
    本题可以离线。
    所以我们先对询问排序,然后按照Kruskal的思路,用并查集维护连通块,对每个连通块内建权值线段树。
    合并两个连通块时,做线段树合并即可。
    然后对于询问,在当前块内查询即可。
    时间复杂度(O(nlog n))。

    C++ Code:

    #include<bits/stdc++.h>
    #include<ext/pb_ds/assoc_container.hpp>
    using namespace std;
    using namespace __gnu_pbds;
    const int N=(1<<17)-1;
    struct node{
        int ls,rs,s;
    }d[N<<5];
    struct asks{
        int u,x,k,id;
        inline bool operator<(const asks&rhs)const{return x<rhs.x;}
    }q[N<<2];
    struct edge{
        int u,v,dis;
        inline bool operator<(const edge&rhs)const{return dis<rhs.dis;}
    }e[N<<2];
    int n,m,Q,cnt=0,rt[N]={0},h[N],fa[N],ans[N<<2];
    int kk,aans;
    tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>s;
    template<typename T>
    inline void read(T&d){
        int c=getchar();d=0;
        for(;!isdigit(c);c=getchar());
        for(;isdigit(c);c=getchar())
        d=(d<<3)+(d<<1)+(c^'0');
    }
    void ins(int&o,int l,int r,int h){
        if(!o)o=++cnt;
        ++d[o].s;
        if(l==r)return;
        int mid=l+r>>1;
        if(h<=mid)ins(d[o].ls,l,mid,h);else
        ins(d[o].rs,mid+1,r,h);
    }
    inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    int node_merge(int ls,int rs){
        if(!ls||!rs)return ls|rs;
        if(!d[ls].ls&&!d[ls].rs){
            d[ls].s+=d[rs].s;
            return ls;
        }
        d[ls].ls=node_merge(d[ls].ls,d[rs].ls);
        d[ls].rs=node_merge(d[ls].rs,d[rs].rs);
        d[ls].s=d[d[ls].ls].s+d[d[ls].rs].s;
        return ls;
    }
    void edge_merge(int now){
        int x=find(e[now].u),y=find(e[now].v);
        if(x!=y){
            fa[y]=x;
            rt[x]=node_merge(rt[x],rt[y]);
        }
    }
    void query(int&o,int l,int r){
        if(l==r)aans=l;else{
            int mid=l+r>>1;
            if(kk<=d[d[o].rs].s)query(d[o].rs,mid+1,r);else{
                kk-=d[d[o].rs].s;
                query(d[o].ls,l,mid);
            }
        }
    }
    int main(){
        memset(d,0,sizeof d);
        read(n),read(m),read(Q);
        for(int i=1;i<=n;++i){
            read(h[i]);
            s.insert(h[i]);
        }
        for(int i=1;i<=n;++i)h[i]=s.order_of_key(h[i]);
        for(int i=1;i<=n;++i)ins(rt[i],0,N,h[i]);
        for(int i=1;i<=m;++i)read(e[i].u),read(e[i].v),read(e[i].dis);
        sort(e+1,e+m+1);
        for(int i=1;i<=Q;++i)read(q[i].u),read(q[i].x),read(q[i].k),q[i].id=i;
        sort(q+1,q+Q+1);
        e[m+1].dis=0x7fffffff;
        for(int i=1;i<=n;++i)fa[i]=i;
        for(int pe=1,pq=1;pq<=Q;){
            if(e[pe].dis<=q[pq].x)edge_merge(pe++);else{
                int u=find(q[pq].u);
                if(d[rt[u]].s<q[pq].k){
                    ans[q[pq++].id]=-1;
                    continue;
                }
                aans=0;
                kk=q[pq].k;
                query(rt[u],0,N);
                ans[q[pq++].id]=*s.find_by_order(aans);
            }
        }
        for(int i=1;i<=Q;++i)printf("%d
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    UVA 11174 Stand in a Line,UVA 1436 Counting heaps —— (组合数的好题)
    UVA 1393 Highways,UVA 12075 Counting Triangles —— (组合数,dp)
    【Same Tree】cpp
    【Recover Binary Search Tree】cpp
    【Binary Tree Zigzag Level Order Traversal】cpp
    【Binary Tree Level Order Traversal II 】cpp
    【Binary Tree Level Order Traversal】cpp
    【Binary Tree Post order Traversal】cpp
    【Binary Tree Inorder Traversal】cpp
    【Binary Tree Preorder Traversal】cpp
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9354136.html
Copyright © 2020-2023  润新知