码迷,mamicode.com
首页 > 其他好文 > 详细

[HDU5361]In Touch

时间:2018-09-27 14:15:31      阅读:150      评论:0      收藏:0      [点我收藏+]

标签:amp   nal   iter   unsigned   属性   mod   etc   线段   eset   

[HDU5361]In Touch

题目大意:

\(n(n\le2\times10^5)\)个点,每个点有三个属性\(l_i,r_i,c_i\)。表示若\(|i-j|\in[l_i,r_i]\)\(i\)\(j\)有一条长度为\(c_i\)的单向边。求从\(1\)出发到各个点的距离。

思路:

线段树优化建图后跑Dijkstra即可。

源代码:

#include<cstdio>
#include<cctype>
#include<vector>
#include<climits>
#include<functional>
#include<ext/pb_ds/priority_queue.hpp>
inline int getint() {
    register char ch;
    while(!isdigit(ch=getchar()));
    register int x=ch^'0';
    while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    return x;
}
const int N=4e5+1;
typedef long long int64;
int tot,l[N],r[N],c[N],pos[N];
struct Edge {
    int to,w;
};
std::vector<Edge> e[N];
inline void add_edge(const int &u,const int &v,const int &w) {
    e[u].push_back((Edge){v,w});
}
inline void reset() {
    for(register int i=1;i<=tot;i++) {
        e[i].clear();
    }
    tot=0;
}
class SegmentTree {
    #define mid ((b+e)>>1)
    private:
        struct Node {
            int left,right;
        };
        Node node[N];
        int new_node() {
            node[++tot]=(Node){};
            return tot;
        }
    public:
        int root;
        void build(int &p,const int &b,const int &e) {
            p=new_node();
            if(b==e) {
                pos[b]=p;
                return;
            }
            build(node[p].left,b,mid);
            build(node[p].right,mid+1,e);
            add_edge(p,node[p].left,0);
            add_edge(p,node[p].right,0);
        }
        void link(const int &p,const int &b,const int &e,const int &l,const int &r,const int &x,const int &y) const {
            if(l>r) return;
            if(b==l&&e==r) {
                add_edge(x,p,y);
                return;
            }
            if(l<=mid) link(node[p].left,b,mid,l,std::min(mid,r),x,y);
            if(r>mid) link(node[p].right,mid+1,e,std::max(mid+1,l),r,x,y);
        }
    #undef mid
};
SegmentTree sgt;
struct Vertex {
    int id;
    int64 dis;
    bool operator > (const Vertex &rhs) const {
        return dis>rhs.dis;
    }
};
int64 dis[N];
__gnu_pbds::priority_queue<Vertex,std::greater<Vertex> > q;
__gnu_pbds::priority_queue<Vertex,std::greater<Vertex> >::point_iterator p[N];
inline void dijkstra() {
    for(register int i=1;i<=tot;i++) {
        p[i]=q.push((Vertex){i,dis[i]=i==pos[1]?0:LLONG_MAX});
    }
    while(!q.empty()&&q.top().dis!=LLONG_MAX) {
        const int x=q.top().id;
        q.pop();
        for(register unsigned i=0;i<e[x].size();i++) {
            const int &y=e[x][i].to,&w=e[x][i].w;
            if(dis[x]+w<dis[y]) {
                q.modify(p[y],(Vertex){y,dis[y]=dis[x]+w});
            }
        }
    }
    q.clear();
}
int main() {
    for(register int T=getint();T;T--) {
        const int n=getint();
        sgt.build(sgt.root,1,n);
        for(register int i=1;i<=n;i++) l[i]=getint();
        for(register int i=1;i<=n;i++) r[i]=getint();
        for(register int i=1;i<=n;i++) c[i]=getint();
        for(register int i=1;i<=n;i++) {
            sgt.link(1,1,n,std::max(1,i-r[i]),i-l[i],pos[i],c[i]);
            sgt.link(1,1,n,i+l[i],std::min(i+r[i],n),pos[i],c[i]);
        }
        dijkstra();
        for(register int i=1;i<=n;i++) {
            printf("%lld%c",dis[pos[i]]!=LLONG_MAX?dis[pos[i]]:-1," \n"[i==n]);
        }
        reset();
    }
    return 0;
}

[HDU5361]In Touch

标签:amp   nal   iter   unsigned   属性   mod   etc   线段   eset   

原文地址:https://www.cnblogs.com/skylee03/p/9712469.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!