[CF787D]Legacy

NOId1t1有这种线段树优化建边的部分分,然后发现还不会。。。

思想就是化为两棵线段树,一棵代表出一棵代表入。每棵树内部就正常那么连边,然后点连到区间就相当于把区间按线段树拆法拆成log个区间,内部yy一下就行了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,int> P;
const int N=500000;
const ll inf=1e16;
inline int read(){
    int r=0,c=getchar();
    while(!isdigit(c))c=getchar();
    while(isdigit(c))r=r*10+c-'0',c=getchar();
    return r;
}
struct Edge{
    int to,nxt,w;
}e[N<<2];
int n,m,S;
int head[N<<2],cnt=1;
void add(int u,int v,int w){
    e[cnt]=(Edge){v,head[u],w};
    head[u]=cnt++;
}
struct Node{
    int l,r;
}T[N<<2];
#define L T[o].l
#define R T[o].r
#define M (L+R>>1)
#define ls o<<1
#define rs o<<1|1
void build(int o,int l,int r){
    T[o]=(Node){l,r};
    if(l==r){
        add(o,o+N,0);
        add(o+N,o,0);
        return;
    }
    build(ls,L,M);
    build(rs,M+1,R);
    add(ls,o,0);add(o+N,(ls)+N,0);
    add(rs,o,0);add(o+N,(rs)+N,0);
}
int ql,qr,tmp,ww,tp;
void find(int o){
    if(ql<=L&&R<=qr){
        if(tp<3)tmp=o;
        else tmp=o+N;
        return;
    }
    if(ql<=M)find(ls);
    if(qr>M) find(rs);
}
void upd(int o){
    if(ql<=L&&R<=qr){
        if(tp<3)add(tmp,o+N,ww);
        else add(o,tmp,ww);
        return;
    }
    if(ql<=M)upd(ls);
    if(qr>M) upd(rs);
}
ll dis[N<<2];bool vis[N<<2];
priority_queue<P,vector<P>,greater<P> >q;
void dij(){
    fill(dis,dis+(N<<1),inf);
    ql=qr=S;tp=1;find(1);S=tmp;
    q.push(P(dis[S]=0,S));
    while(!q.empty()){
        P x=q.top();q.pop();
        ll d=x.first;int u=x.second;
        if(vis[u])continue;vis[u]=1;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].to,w=e[i].w;
            if(d+w<dis[v]){
                dis[v]=d+w;
                q.push(P(dis[v],v)); 
            }
        }
    }
}
void init(){
    n=read();m=read();
    S=read();
    build(1,1,n);
    while(m--){
        tp=read();
        int u,v,l,r;
        if(tp==1){
            u=read();v=read();ww=read();
            ql=qr=u;find(1);
            ql=qr=v;upd(1);
        }
        else{
            u=read();l=read(),r=read();ww=read();
            ql=qr=u;find(1);
            ql=l,qr=r;upd(1);
        }
    }
}
void prt(int o){
    if(L==R){
        if(dis[o+N]==inf)dis[o+N]=-1;
        printf("%lld ",dis[o+N]);
        return;
    }
    prt(ls);prt(rs);
}
int main(){
    init();
    dij();
    prt(1);
}

 

posted @ 2019-07-21 22:22  orzzz  阅读(260)  评论(0编辑  收藏  举报