数组开太大会TLE….
会TLE….
TLE…………
咳咳,正常建图的话要一个点一个点那么指
区间指怎么办
可以想到线段树,开两个线段树A,B
线段树A的儿子指父亲,代表想从一个区间出发也可以由包含它的更大的区间出发
线段树B的父亲指儿子,代表能到达区间
l...r
l
.
.
.
r
的点更能到达其中一小部分点
连边的时候A的点指向一个新的中转点S,T连B的点,S指向T,代价为1
所有B线段树上的点指向A线段树相应位置上的点,代表到达这个点可以接着从这个点出发
注意是无向图
代码如下:
#include<algorithm>
#include<cstring>
#include<ctype.h>
#include<cstdio>
#include<queue>
#define pii pair<int,int>
#define mp make_pair
#define N 9000005
using namespace std;
inline int read(){
int x=0,f=1;char c;
do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c));
do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c));
return x*f;
}
struct Node{
Node *ls,*rs;
int id,l,r;
Node():ls(NULL),rs(NULL){}
}*rootS=new Node,*rootT=new Node,pp[N];
priority_queue<pii,vector<pii>,greater<pii> >q;
int fir[N],pos[N],dis[N],belong[N],tot;
bool b[N];
int n,m,p,x,y,x1,y1,top,cnt;
struct Edge{
int to,nex,k;
Edge(int _=0,int __=0,int ___=0):to(_),nex(__),k(___){}
}nex[N];
inline void add(int x,int y,int k){
nex[++top]=Edge(y,fir[x],k);
fir[x]=top;
}
void maketree(int l,int r,Node *x,Node *y){
x->l=l;x->r=r;y->l=l;y->r=r;
x->id=++cnt;y->id=++cnt;
add(y->id,x->id,0);
if(l==r){
pos[l]=x->id;
return;
}
int mid=(l+r)>>1;
maketree(l,mid,x->ls=&pp[tot++],y->ls=&pp[tot++]);
maketree(mid+1,r,x->rs=&pp[tot++],y->rs=&pp[tot++]);
add(x->ls->id,x->id,0);add(x->rs->id,x->id,0);
add(y->id,y->ls->id,0);add(y->id,y->rs->id,0);
return;
}
void AddIn(int x,int y,int to,Node *k){
if(k->l>=x && k->r<=y)
return add(k->id,to,0);
int mid=(k->l+k->r)>>1;
if(mid>=y) AddIn(x,y,to,k->ls);
else if(mid<x) AddIn(x,y,to,k->rs);
else AddIn(x,y,to,k->ls),AddIn(x,y,to,k->rs);
return;
}
void AddOut(int x,int y,int from,Node *k){
if(k->l>=x && k->r<=y)
return add(from,k->id,0);
int mid=(k->l+k->r)>>1;
if(mid>=y) AddOut(x,y,from,k->ls);
else if(mid<x) AddOut(x,y,from,k->rs);
else AddOut(x,y,from,k->ls),AddOut(x,y,from,k->rs);
return;
}
inline void Dijkstra(){
memset(dis,0x7f7f7f7f,sizeof dis);
q.push(mp(dis[pos[p]]=0,pos[p]));
while(!q.empty()){
int x=q.top().second;q.pop();
if(b[x]) continue;
b[x]=true;
for(int i=fir[x];i;i=nex[i].nex)
if(dis[nex[i].to]>dis[x]+nex[i].k){
dis[nex[i].to]=dis[x]+nex[i].k;
q.push(mp(dis[nex[i].to],nex[i].to));
}
}
}
int main(){
n=read();m=read();p=read();
maketree(1,n,rootS,rootT);
for(int i=1;i<=m;i++){
x=read();y=read();
x1=read();y1=read();
cnt++;
AddIn(x,y,cnt,rootS);
add(cnt,cnt+1,1);
cnt++;
AddOut(x1,y1,cnt,rootT);
cnt++;
AddIn(x1,y1,cnt,rootS);
add(cnt,cnt+1,1);
cnt++;
AddOut(x,y,cnt,rootT);
}
Dijkstra();
for(int i=1;i<=n;i++)
printf("%d\n",dis[pos[i]]);
return 0;
}