Description
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号国家能到任意一个国家。
注意:可能有重边
Input
第一行三个数N,M,P。N<=500000,M<=100000。
后M行,每行4个数A,B,C,D。1<=A<=B<=N,1<=C<=D<=N。
Output
N行,第i行表示P号国家到第i个国家最少需要经过几条路。显然第P行应该是0。
Sample Input
5 3 4
1 2 4 5
5 5 4 4
1 1 3 3
Sample Output
1
1
2
0
1
HINT
Source
seter翻译
线段树优化建图的最短路.(咦这个真的算线段树优化建图吗..我个人的定义可能不太严谨
可能卡内存..最后试了试边数组开300W就能过
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<set>
#define MAXN 500010
#define GET (ch>='0'&&ch<='9')
#define lchild rt<<1,l,mid
#define rchild rt<<1|1,mid+1,r
#define ln rt<<1
#define rn rt<<1|1
using namespace std;
int n,m,p,top,tp,cnt;
int a,b,c,d,tl,tr;
set<int> s;
set<int>::iterator it,sta[MAXN];
inline void in(int &x)
{
char ch=getchar();x=0;
while (!GET) ch=getchar();
while (GET) x=x*10+ch-'0',ch=getchar();
}
int root[MAXN],dis[MAXN];
struct edge { int al,ar;edge *next; }e[MAXN*6],*prev[MAXN*2+50000];
inline void build(int rt=1,int l=1,int r=n)
{
if (l==r) { root[l]=rt;return; }
int mid=(l+r)>>1;build(lchild);build(rchild);
}
inline void insert(int rt,int l,int r,int L,int R)
{
int mid=(L+R)>>1;
if (l<=L&&r>=R) { e[++top].al=tl;e[top].ar=tr;e[top].next=prev[rt];prev[rt]=&e[top];return; }
if (r<=mid) insert(ln,l,r,L,mid);
else if (l>mid) insert(rn,l,r,mid+1,R);
else insert(ln,l,mid,L,mid),insert(rn,mid+1,r,mid+1,R);
}
int main()
{
int x,t;
for (in(n),in(m),in(p),build();m;m--)
in(a),in(b),in(c),in(d),
tl=c,tr=d,insert(1,a,b,1,n),
tl=a,tr=b,insert(1,c,d,1,n);
queue<int> q;q.push(p);
for (int i=1;i<=n+1;i++) if (i!=p) s.insert(i);
while (!q.empty())
{
x=q.front();t=dis[x];q.pop();x=root[x];
for (;x;prev[x]=0x0,x>>=1)
for (edge *i=prev[x];i;i=i->next)
{
for (cnt=0,it=s.lower_bound(i->al);*it<=i->ar;it++) dis[*it]=t+1,q.push(*it),sta[++cnt]=it;
while (cnt) s.erase(sta[cnt--]);
}
}
for (int i=1;i<=n;i++) printf("%d\n",dis[i]);
}