zoukankan      html  css  js  c++  java
  • [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;
    }
    
  • 相关阅读:
    python 继承与组合
    google浏览器安装不上的绝望经历
    python 类,对象
    Javascript学习笔记——闭包
    面试小结:html/css实现元素居中
    @清晰掉 qsort()
    @清晰掉 sprintf sscanf双胞胎
    @清晰掉 GDB调试器中的战斗机
    @大脑练习: 计算两个矩阵的乘积
    js测试用
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9354136.html
Copyright © 2011-2022 走看看