Codeforces 786 B. Legacy

题目链接:http://codeforces.com/contest/786/problem/B


  典型线段树优化连边,线段树上的每一个点表示这个区间的所有点,然后边数就被优化为了至多${nlogn}$条,注意要区分$2$,$3$操作(建两棵线段树),然后最短路即可。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<cstdlib>
  6 #include<cmath>
  7 #include<cstring>
  8 using namespace std;
  9 #define maxn 1001000
 10 #define llg long long
 11 #define INC 300000
 12 #define SIZE 2000000 
 13 #define inf (llg)1e18
 14 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
 15 llg n,dis[maxn],dl[SIZE+10],head,tail,pos[maxn];
 16 bool bj[maxn];
 17 
 18 vector<llg>a[maxn],val[maxn];
 19 
 20 inline int getint()
 21 {
 22        int w=0,q=0; char c=getchar();
 23        while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); 
 24        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w;
 25 }
 26 
 27 void link(llg x,llg y,llg z) {a[x].push_back(y),val[x].push_back(z);}
 28 
 29 void build(llg o,llg l,llg r)
 30 {
 31     if (l==r)
 32     {
 33         pos[l]=o;
 34         return ;
 35     }
 36     llg mid=(l+r)>>1,lc=o<<1,rc=o<<1|1;
 37     build(lc,l,mid); build(rc,mid+1,r);
 38 }
 39 
 40 void find(llg o,llg l,llg r,llg L,llg R,llg val,bool f,llg v)
 41 {
 42     if (l>=L && r<=R)
 43     {
 44         if (f) link(pos[v],o,val);else link(o+INC,pos[v],val);
 45         return ;
 46     }
 47     llg mid=(l+r)>>1,lc=o<<1,rc=o<<1|1;
 48     if (mid>=L) find(lc,l,mid,L,R,val,f,v);
 49     if (mid<R) find(rc,mid+1,r,L,R,val,f,v);
 50 }
 51 
 52 
 53 
 54 void link_fa(llg o,llg l,llg r)
 55 {
 56     for (llg i=l;i<=r;i++) link(o,pos[i],0),link(pos[i],o+INC,0);
 57     if (l==r) return ;
 58     llg mid=(l+r)>>1,lc=o<<1,rc=o<<1|1;
 59     link_fa(lc,l,mid); link_fa(rc,mid+1,r);
 60 }
 61 
 62 void init()
 63 {
 64     llg t,v,u,w,l,r,s,q;
 65     n=getint(),q=getint(),s=getint();
 66     build(1,1,n);
 67     for (llg i=1;i<=q;i++)
 68     {
 69         t=getint();
 70         if (t==1) 
 71         {
 72             v=getint(),u=getint(),w=getint();
 73             link(pos[v],pos[u],w);
 74         }
 75         if (t==2)
 76         {
 77             v=getint(),l=getint(),r=getint(),w=getint();
 78             find(1,1,n,l,r,w,1,v);
 79         }
 80         if (t==3)
 81         {
 82             v=getint(),l=getint(),r=getint(),w=getint();
 83             find(1,1,n,l,r,w,0,v);
 84         }
 85     }
 86     link_fa(1,1,n);
 87     for (llg i=1;i<maxn;i++) dis[i]=inf;
 88     dis[pos[s]]=0;
 89     dl[1]=pos[s],head=0,tail=1;
 90 }
 91 
 92 void spfa()
 93 {
 94     llg w,x,v;
 95     do
 96     {
 97         head%=SIZE; head++;
 98         x=dl[head]; w=a[x].size(); bj[x]=0;
 99         for (llg i=0;i<w;i++)
100         {
101             v=a[x][i];
102             if (dis[v]>dis[x]+val[x][i])
103             {
104                 dis[v]=dis[x]+val[x][i];
105                 if (!bj[v])
106                 {
107                     bj[v]=1;
108                     tail%=SIZE; tail++;
109                     dl[tail]=v;
110                 }
111             }
112         }
113     }while (head!=tail);
114 }
115 
116 int main()
117 {
118     yyj("graph");
119     init();
120     spfa();
121     for (llg i=1;i<=n;i++) if (dis[pos[i]]==inf) printf("-1 "); else printf("%lld ",dis[pos[i]]);
122     return 0;
123 }
原文地址:https://www.cnblogs.com/Dragon-Light/p/6613132.html