zoukankan      html  css  js  c++  java
  • CF786B/CF787D

    线段树优化建图板子题

    首先暴力建图显然是不可取的,但是我们发现建图要求是点和区间之间的问题,所以考虑用线段树优化

    但是怎么优化呢?

    如果用一棵线段树很难处理同时出边和入边,因此我们考虑用两棵线段树(类似拆点),一棵线段树作为起点,另一棵线段树作为终点,然后在两棵线段树之间连边即可

    这样的话连边的方式也就是起点线段树中一个节点(代表一个点或一段区间)向终点线段树中一个节点(代表一个点或一段区间),起点线段树从下向上连边,终点线段树从上向下连边,终点线段树叶节点向对应起点线段树叶节点连边即可

    贴代码:

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #define ll long long
    #define rt1 (rt<<1)
    #define rt2 ((rt<<1)|1)
    using namespace std;
    struct Edge
    {
        int nxt;
        int to;
        ll val;
    }edge[5000005];
    struct node
    {
        int p;
        ll v;
        node (){}
        node (int x,ll y):p(x),v(y){}
        friend bool operator < (node a,node b)
        {
            return a.v>b.v;
        }
    };
    int pos1[100005];
    int pos2[100005];
    int head[800005];
    bool vis[800005];
    ll dis[800005];
    int cnt=1;
    int n,q,s;
    void add(int l,int r,ll w)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        head[l]=cnt++;
    }
    void buildtree1(int rt,int l,int r)
    {
        if(l==r){pos1[l]=rt;return;}
        int mid=(l+r)>>1;
        buildtree1(rt1,l,mid),buildtree1(rt2,mid+1,r);
        add(rt1,rt,0),add(rt2,rt,0);
    }
    void buildtree2(int rt,int l,int r)
    {
        if(l==r){pos2[l]=rt+4*n;return;}
        int mid=(l+r)>>1;
        buildtree2(rt1,l,mid),buildtree2(rt2,mid+1,r);
        add(rt+4*n,rt1+4*n,0),add(rt+4*n,rt2+4*n,0);
    }
    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;
    }
    void query_add1(int rt,int l,int r,int lq,int rq,int v,ll w)//区间->点
    {
        if(l>=lq&&r<=rq){add(rt,v,w);return;}
        int mid=(l+r)>>1;
        if(lq<=mid)query_add1(rt1,l,mid,lq,rq,v,w);
        if(rq>mid)query_add1(rt2,mid+1,r,lq,rq,v,w);
    }
    void query_add2(int rt,int l,int r,int lq,int rq,int v,ll w)//点->区间
    {
        if(l>=lq&&r<=rq){add(v,rt+4*n,w);return;}
        int mid=(l+r)>>1;
        if(lq<=mid)query_add2(rt1,l,mid,lq,rq,v,w);
        if(rq>mid)query_add2(rt2,mid+1,r,lq,rq,v,w);
    }
    void diji()
    {
        memset(dis,0x3f,sizeof(dis));
        dis[pos1[s]]=dis[pos2[s]]=0;
        priority_queue <node> Q;
        Q.push(node(pos1[s],0));
        while(!Q.empty())
        {
            node u=Q.top();
            Q.pop();
            if(vis[u.p])continue;
            vis[u.p]=1;
            for(int i=head[u.p];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u.p]+edge[i].val&&!vis[to])dis[to]=dis[u.p]+edge[i].val,Q.push(node(to,dis[to]));
            }
        }
        for(int i=1;i<=n;i++)
        {
            if(dis[pos2[i]]==0x3f3f3f3f3f3f3f3fll)printf("-1 ");
            else printf("%lld ",dis[pos2[i]]);
        }
        printf("
    ");
    }
    int main()
    {
        read(n),read(q),read(s);
        buildtree1(1,1,n),buildtree2(1,1,n);
        for(int i=1;i<=n;i++)add(pos2[i],pos1[i],0);
        while(q--)
        {
            int typ;
            ll w;
            read(typ);
            if(typ==1)
            {
                int st,ed;
                read(st),read(ed),read(w);
                add(pos1[st],pos2[ed],w);
            }else if(typ==2)
            {
                int lq,rq,st;
                read(st),read(lq),read(rq),read(w);
                query_add2(1,1,n,lq,rq,pos1[st],w);
            }else
            {
                int lq,rq,ed;
                read(ed),read(lq),read(rq),read(w);
                query_add1(1,1,n,lq,rq,pos2[ed],w);
            }
        }
        diji();
        return 0;
    }
  • 相关阅读:
    navigator 对象
    面向对象 ( OO ) 的程序设计——继承
    面向对象 ( OO ) 的程序设计——创建对象
    面向对象 ( OO ) 的程序设计——理解对象
    芯片知识扫盲
    8位、16位、32位单片机中的“XX位”指什么?
    stm32库函数建工程和使用Keil自带库建工程有没有区别?发现了同样的程序在两种情况下keil自带库可以运行的情况,不知是什么原因
    关于输出的看法
    4-鸡肉为何如此受欢迎
    7-发音规则(弱读,缩写,其他)
  • 原文地址:https://www.cnblogs.com/zhangleo/p/11131125.html
Copyright © 2011-2022 走看看