10
7
2015
0

3073: [Pa2011]Journeys

3073: [Pa2011]Journeys

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 32  Solved: 17
[Submit][Status][Discuss]

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

    RZZ的模拟赛里的一道题、、、比赛的时候直接放弃了满分写了个暴力上去。。。然后就连一等线都没有到。。。

    标算是在线段树上挂链。。将每一条边在线段树上的区间找出来然后连边。。

    用bfs求最短路。。对于一个点将覆盖他的区间提取出来,扩展他连向的区间。。用并查集维护一个点是否已经被bfs过。。

    刚开始写了没有路径压缩的并查集。。然后很愉快的T了。。。真不知道当时是怎么想的。。。

#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=500010;
struct data{int x,y1,y2,next,pre;} e[N<<3];
struct Tree{int l,r;} tree[N<<2];
int head[N<<2],a,b,c,d,n,m,p,f[N],dis[N],cnt,vis[N<<2],now,V[N];
queue <int> q;
int read(){
	int x = 0,f = 1,c = getchar();
	while (c<'0' || c>'9') {if (c=='-') f = -1;c = getchar();}
	while (c>='0' && c<='9') x = x*10+c-'0',c = getchar();
	return x*f;
}
void Insert(int x,int y1,int y2){
	e[++cnt].x = x;e[cnt].y1 = y1;e[cnt].y2 = y2;
	e[cnt].next = head[x];head[x] = cnt;
}
void Build(int pos,int l,int r){
	tree[pos].l = l;tree[pos].r = r;
	if (l==r) return;
	int mid = (l+r)>>1;
	Build(pos<<1,l,mid);
	Build(pos<<1|1,mid+1,r);
}
void Add(int pos,int l,int r,int valx,int valy){
	if (tree[pos].l==l && tree[pos].r==r){Insert(pos,valx,valy);return;}
	int mid = (tree[pos].l+tree[pos].r)>>1;
	if (r<=mid) Add(pos<<1,l,r,valx,valy);
	else if (l>mid) Add(pos<<1|1,l,r,valx,valy);
	else Add(pos<<1,l,mid,valx,valy),Add(pos<<1|1,mid+1,r,valx,valy);
}
int get(int x){return f[x]==x?x:f[x] = get(f[x]);}
void find(int x){
	int pos = 1;
	for (;;){
		if (!vis[pos]){
			vis[pos] = 1;
			for (int i=head[pos];i;i=e[i].next){
				int t=get(e[i].y1);
				while (t<=e[i].y2 && t!=0){
					V[t] = 1;
					dis[t] = dis[now]+1;
					q.push(t);f[t] = t+1;
					t = get(f[t]);
				}
			}
		}
		if (tree[pos].l==tree[pos].r) return;
		int mid = (tree[pos].l+tree[pos].r)>>1;
		if (x<=mid) pos = pos<<1;
		else pos = pos<<1|1;
	}
}
int main(){
	n = read();m = read();p = read();
	Build(1,1,n);
	for (int i=1;i<=m;i++){
		a = read();b = read();c = read();d = read();
		Add(1,a,b,c,d);Add(1,c,d,a,b);
	}
	for (int i=1;i<=n;i++) f[i] = i;
	q.push(p);f[p] = p+1;dis[p] = 0;V[p] = 1;
	while (!q.empty()){now = q.front();q.pop();find(now);}
	for (int i=1;i<=n;i++) printf("%d\n",dis[i]);
}
Category: BZOJ题解 | Tags: | Read Count: 735

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com