• bzoj 3073 Journeys —— 线段树优化连边


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3073

    建两棵线段树,一棵从下往上连边,一棵从上往下连边,叶子节点之间也有连边;

    区间向区间连边时,可以新建一个节点,log2n 条边就能变成 2logn 条边;

    注意区间向区间连边也要连反边,别忘了连反边时 ++cnt !

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define mid ((l+r)>>1)
    using namespace std;
    int const xxn=5e5+5,xn=4e6+5,xm=3e7+5;
    int n,m,hd[xn],ct,to[xm],nxt[xm],w[xm],dis[xn];
    int rt[2],cnt,ls[xxn<<2],rs[xxn<<2],st[xxn],ed[xxn];
    bool vis[xn];
    struct N{
      int d,id;
      bool operator < (const N &y) const
      {return d==y.d?id<y.id:d>y.d;}
    };
    priority_queue<N>q;
    int rd()
    {
      int ret=0,f=1; char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
      while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
      return f?ret:-ret;
    }
    int gt[20];
    void wr(int x)
    {
      if(!x){puts("0"); return;}
      if(x<0)putchar('-'),x=-x;
      int t=0;
      while(x)gt[++t]=x%10,x/=10;
      for(int i=t;i;i--)putchar(gt[i]+'0');
      puts("");
    }
    void add(int x,int y,int z){to[++ct]=y; nxt[ct]=hd[x]; w[ct]=z; hd[x]=ct;}
    void build(int x,int l,int r,bool tp)
    {
      if(l==r)
        {
          if(!tp)st[l]=x; else ed[l]=x;
          return;
        }
      ls[x]=++cnt; rs[x]=++cnt;
      build(ls[x],l,mid,tp); build(rs[x],mid+1,r,tp);
      if(!tp)add(ls[x],x,0),add(rs[x],x,0);
      else add(x,ls[x],0),add(x,rs[x],0);
    }
    void link(int x,int l,int r,int L,int R,int c,bool tp)
    {
      if(l>=L&&r<=R)
        {
          if(!tp)add(x,c,1); else add(c,x,0);
          return;
        }
      if(mid>=L)link(ls[x],l,mid,L,R,c,tp);
      if(mid<R)link(rs[x],mid+1,r,L,R,c,tp);
    }
    void dij(int s)
    {
      memset(dis,0x3f,sizeof dis);
      dis[s]=0; q.push((N){0,s});
      while(q.size())
        {
          int x=q.top().id; q.pop();
          if(vis[x])continue; vis[x]=1;
          for(int i=hd[x],u;i;i=nxt[i])
        if(dis[u=to[i]]>dis[x]+w[i])
          dis[u]=dis[x]+w[i],q.push((N){dis[u],u});
        }
    }
    int main()
    {
      n=rd(); m=rd(); int p=rd();
      rt[0]=++cnt; build(rt[0],1,n,0);
      rt[1]=++cnt; build(rt[1],1,n,1);
      for(int i=1;i<=n;i++)add(ed[i],st[i],0);
      for(int i=1,a,b,c,d;i<=m;i++)
        {
          a=rd(); b=rd(); c=rd(); d=rd(); int t=++cnt;
          link(rt[0],1,n,a,b,t,0); link(rt[1],1,n,c,d,t,1);
          t=++cnt;//!!!
          link(rt[0],1,n,c,d,t,0); link(rt[1],1,n,a,b,t,1);
        }
      dij(ed[p]);
      for(int i=1;i<=n;i++)wr(dis[ed[i]]);
      return 0;
    }
  • 相关阅读:
    SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long 解决方法
    Apache Commons 简介
    CSS设置只显示两行文字
    HTML中关于动态创建的标签无法绑定js事件的解决方法:.on()方法的 [.selector]
    AISing Programming Contest 2021(AtCoder Beginner Contest 202)E
    CF620E New Year Tree(dfs序+线段树)
    HDU6955 2021多校 Xor sum(字典树+前缀和异或)
    HDU6959 2021多校 zoto(莫队+分块)
    CF1285D Dr. Evil Underscores(分治)
    CF706D Vasiliy's Multiset(字典树的删除)
  • 原文地址:https://www.cnblogs.com/Zinn/p/9869683.html
Copyright © 2020-2023  润新知