传送门
Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路。N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a,b),(c,d)表示,对于任意两个国家x,y,如果a<=x<=b,c<=y<=d,那么在xy之间建造一条道路。Seter保证一条道路不会修建两次,也保证不会有一个国家与自己之间有道路。
Seter好不容易建好了所有道路,他现在在位于P号的首都。Seter想知道P号国家到任意一个国家最少需要经过几条道路。当然,Seter保证P号国家能到任意一个国家。
题解:线段树优化构图。
区间连边直接在线段树上连就好了。连边时新建点就不用 log2n ,可以做到 logn 。
#include
using namespace std;
inline int read(){
char ch=getchar();int i=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}
return i*f;
}
inline void W(int x){
static int buf[50];
if(!x){putchar('0');return;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10;x/=10;}
while(buf[0]){putchar(buf[buf[0]--]+'0');}
}
const int Maxn=5e5+50;
int n,m,s,posIn[Maxn<<2],posOut[Maxn<<2],dis[Maxn<<3],tot,tot2,vis[Maxn<<3],pos[Maxn];
struct E{
E *nxt;
int to,val;
E():nxt(NULL){}
}Pool[Maxn*18],*pool=Pool,*edge[Maxn<<3];
inline void push_back(E *&t,int to,int val){
++pool;
pool->to=to;
pool->nxt=t;
pool->val=val;
t=pool;
}
inline void build(int k,int l,int r){
(tot2?posIn[k]=++tot:posOut[k]=++tot);
if(k!=1){
if(tot2){
push_back(edge[posIn[k>>1]],posIn[k],0);
}else{
push_back(edge[posOut[k]],posOut[k>>1],0);
}
}
if(l==r){
if(tot2)push_back(edge[posIn[k]],posOut[k],0),pos[l]=posIn[k];
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);build(k<<1|1,mid+1,r);
}
inline void findpos(int k,int l,int r,int L,int R,int t){
if(L<=l&&r<=R){
if(t)push_back(edge[posOut[k]],tot,1);
else push_back(edge[tot],posIn[k],0);
return;
}
int mid=(l+r)>>1;
if(R<=mid)findpos(k<<1,l,mid,L,R,t);
else if(L>mid)findpos(k<<1|1,mid+1,r,L,R,t);
else findpos(k<<1,l,mid,L,R,t),findpos(k<<1|1,mid+1,r,L,R,t);
}
typedef pair<int,int> pii;
priority_queue< pii,vector ,greater >q;
inline void dijkstra(int S){
memset(dis,0x3f,sizeof(dis));
dis[S]=0;q.push(make_pair(0,S));
while(!q.empty()){
if(vis[q.top().second]){q.pop();continue;}
pii t=q.top();q.top();vis[t.second]=1;
for(E *e=edge[t.second];e;e=e->nxt){
if(dis[e->to]>dis[t.second]+e->val){
dis[e->to]=dis[t.second]+e->val;
q.push(make_pair(dis[e->to],e->to));
}
}
}
}
inline void getans(int k,int l,int r){
if(l==r){
W(dis[posOut[k]]);putchar('\n');
return;
}
int mid=(l+r)>>1;
getans(k<<1,l,mid);
getans(k<<1|1,mid+1,r);
}
int main(){
n=read(),m=read(),s=read();
build(1,1,n);
tot2=tot;
build(1,1,n);
for(int i=1;i<=m;i++){
int L1=read(),R1=read(),L2=read(),R2=read();
++tot;
findpos(1,1,n,L1,R1,1);
findpos(1,1,n,L2,R2,0);
++tot;
findpos(1,1,n,L2,R2,1);
findpos(1,1,n,L1,R1,0);
}
dijkstra(pos[s]);
getans(1,1,n);
}