bzoj 3073 Journeys Posted on 2019-05-21 | Views: 线段树优化连边. 边是双向的.开两颗线段树, $A$ 里面节点表示一条有向边的起点,儿子向父亲连边, $B$ 里面节点表示一条有向边的终点,父亲向儿子连边, $B$ 向 $A$ 中对应的节点连边. 区间连边时,新建一个节点,将区间在线段树上拆成 $log$ 个区间进行连边就好了. 最后跑一次 $Dijkstra$ . 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130#include<bits/stdc++.h>using namespace std;typedef long long ll;inline int read(){ int out=0,fh=1; char jp=getchar(); while ((jp>'9'||jp<'0')&&jp!='-') jp=getchar(); if (jp=='-') fh=-1,jp=getchar(); while (jp>='0'&&jp<='9') out=out*10+jp-'0',jp=getchar(); return out*fh;}const int MAXN=5e5+10,MAXM=2220000;int n,m,S;int ecnt=0,head[MAXM],to[MAXM],nx[MAXM],val[MAXM];void addedge(int u,int v,int w){ ++ecnt; to[ecnt]=v; nx[ecnt]=head[u]; val[ecnt]=w; head[u]=ecnt;}struct node{ int ls,rs;}Tree[MAXN<<2];#define root Tree[o]int pos[MAXN],tot=0;void bd1(int &o,int l,int r){ o=++tot; if(l==r) { pos[l]=o; return; } int mid=(l+r)>>1; bd1(root.ls,l,mid); bd1(root.rs,mid+1,r); addedge(root.ls,o,0); addedge(root.rs,o,0);}void bd2(int &o,int l,int r){ o=++tot; if(l==r) { addedge(o,pos[l],0); return; } int mid=(l+r)>>1; bd2(root.ls,l,mid); bd2(root.rs,mid+1,r); addedge(o,root.ls,0); addedge(o,root.rs,0);}void upd1(int o,int l,int r,int L,int R){ if(L<=l && r<=R) { addedge(o,tot,1); return; } int mid=(l+r)>>1; if(L<=mid) upd1(root.ls,l,mid,L,R); if(R>mid) upd1(root.rs,mid+1,r,L,R);}void upd2(int o,int l,int r,int L,int R){ if(L<=l && r<=R) { addedge(tot,o,1); return; } int mid=(l+r)>>1; if(L<=mid) upd2(root.ls,l,mid,L,R); if(R>mid) upd2(root.rs,mid+1,r,L,R);}int rt1=0,rt2=0;int vis[MAXM],dis[MAXM];typedef pair<int,int> pii;#define mp make_pairpriority_queue<pii> q;void Dijkstra(){ memset(dis,0x7f,sizeof dis); dis[pos[S]]=0; q.push(mp(0,pos[S])); while(!q.empty()) { int u=q.top().second; q.pop(); if(vis[u]) continue; vis[u]=1; for(int i=head[u];i;i=nx[i]) { int v=to[i]; if(dis[v]-dis[u]>val[i]) { dis[v]=dis[u]+val[i]; q.push(mp(-dis[v],v)); } } }}int main(){ n=read(),m=read(),S=read(); bd1(rt1,1,n); bd2(rt2,1,n); while(m--) { int x1=read(),y1=read(),x2=read(),y2=read(); ++tot;upd1(rt1,1,n,x1,y1);upd2(rt2,1,n,x2,y2); ++tot;upd1(rt1,1,n,x2,y2);upd2(rt2,1,n,x1,y1); } Dijkstra(); for(int i=1;i<=n;++i) printf("%d\n",dis[pos[i]]>>1); return 0;}