CF786B/CF787D Legacy

题目描述:

luogu

cf

cf

题解:

最短路+线段树优化建图。

考虑本题的边是点->点、段->点和点->段,我们可以建线段树然后拆成入点和出点。

入点:儿子->父亲,边权为0;

出点:父亲->儿子,边权为0;

叶子:出点->入点,边权为0;

那么连续的一段可以用不超过$log\;n$个节点表示,最后跑最短路即可。

代码:

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 100050;
const ll  Inf = 0x3f3f3f3f3f3f3f3fll;
template<typename T>
inline void read(T&x)
{
    T f = 1,c = 0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
    x = f*c;
}
int n,Q,S,hed[N*10],cnt,tot;
ll dis[N*10];
bool vis[N*10];
struct EG
{
    int to,nxt;
    ll w;
}e[30*N];
void ae(int f,int t,ll w)
{
    e[++cnt].to = t;
    e[cnt].nxt = hed[f];
    e[cnt].w = w;
    hed[f] = cnt;
}
int sta[N],tl;
struct segtree
{
    int s[N<<2][2];
    void build(int l,int r,int u)
    {
        s[u][0]=++tot,s[u][1]=++tot;
        if(l==r){ae(s[u][1],s[u][0],0);return ;}
        int mid = (l+r)>>1;
        build(l,mid,u<<1),build(mid+1,r,u<<1|1);
        ae(s[u<<1][0],s[u][0],0),ae(s[u<<1|1][0],s[u][0],0);
        ae(s[u][1],s[u<<1][1],0),ae(s[u][1],s[u<<1|1][1],0);
    }
    int query(int l,int r,int u,int qx,int k)
    {
        if(l==r)return s[u][k];
        int mid = (l+r)>>1;
        if(qx<=mid)return query(l,mid,u<<1,qx,k);
        else return query(mid+1,r,u<<1|1,qx,k);
    }
    void query(int l,int r,int u,int ql,int qr,int k)
    {
        if(l==ql&&r==qr){sta[++tl]=s[u][k];return ;}
        int mid = (l+r)>>1;
        if(qr<=mid)query(l,mid,u<<1,ql,qr,k);
        else if(ql>mid)query(mid+1,r,u<<1|1,ql,qr,k);
        else query(l,mid,u<<1,ql,mid,k),query(mid+1,r,u<<1|1,mid+1,qr,k);
    }
    void print(int l,int r,int u)
    {
        if(l==r){if(dis[s[u][0]]==Inf)printf("-1 ");else printf("%lld ",dis[s[u][0]]);return ;}
        int mid = (l+r)>>1;
        print(l,mid,u<<1);print(mid+1,r,u<<1|1);
    }
}tr;
struct Pair
{
    int x;ll y;
    Pair(){}
    Pair(int x,ll y):x(x),y(y){}
    bool operator < (const Pair&a)const{return y>a.y;}
};
priority_queue<Pair>q;
void dij()
{
    memset(dis,0x3f,sizeof(dis));
    S = tr.query(1,n,1,S,0);
    dis[S]=0;q.push(Pair(S,0));
    while(!q.empty())
    {
        Pair tp = q.top();q.pop();
        int u = tp.x;if(vis[u])continue;vis[u] = 1;
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(dis[to]>dis[u]+e[j].w)
            {
                dis[to] = dis[u]+e[j].w;
                q.push(Pair(to,dis[to]));
            }
        }
    }
}
int main()
{
//    freopen("tt.in","r",stdin);
    read(n),read(Q),read(S);
    tr.build(1,n,1);
    for(int op,a,b,c,d,i=1;i<=Q;i++)
    {
        read(op),read(a),read(b),read(c);
        if(op==1)
        {
            a = tr.query(1,n,1,a,0),b = tr.query(1,n,1,b,1);
            ae(a,b,c);
        }else
        {
            read(d);
            if(op==2)
            {
                int f = tr.query(1,n,1,a,0);
                tl = 0;tr.query(1,n,1,b,c,1);
                for(int j=1;j<=tl;j++)
                    ae(f,sta[j],d);
            }else
            {
                tl = 0;tr.query(1,n,1,b,c,0);
                int t = tr.query(1,n,1,a,1);
                for(int j=1;j<=tl;j++)
                    ae(sta[j],t,d);
            }
        }
    }
    dij();
    tr.print(1,n,1);
    puts("");
    return 0;
}
View Code

 

posted @ 2019-07-04 10:23  LiGuanlin  阅读(...)  评论(...编辑  收藏