博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ3073: [Pa2011]Journeys
阅读量:5135 次
发布时间:2019-06-13

本文共 2537 字,大约阅读时间需要 8 分钟。

题解:  暴力建图当然gg 我们考虑用线段树分块建图的思想 因为涉及到两个区间 对着建图 一个线段树不够 考虑用两个线段树 一个作为出树(出树儿子向父亲连边) 一个作为入树(父亲向儿子连边) 每次出树向入树连边 这样建图的话也是mlogn^2的 显然还可以优化 我们采用对于每次连边 用一个超级大源点 这样的话每次连边为log^n级别的 然后对于入树而言 他可以和出树平行连边 这样的话 在本质上 还是两个区间直接产生贡献=>等价于从出树的x节点->入树的y节点->出树的y节点 这样连边跑spfa统计入树答案即可

#include 
#define mp make_pairconst int MAXN=8e5+10;const int inf=1e9;using namespace std;vector
>vec[MAXN<<3];int pos[MAXN],sz,S,n,m,p;void built(int rt,int l,int r){ if(l==r){pos[l]=rt;return ;} vec[rt<<1].push_back(mp(rt,0)); vec[rt<<1|1].push_back(mp(rt,0)); int mid=(l+r)>>1; built(rt<<1,l,mid); built(rt<<1|1,mid+1,r);}void built1(int rt,int l,int r){ vec[rt+sz].push_back(mp(rt,0)); if(l==r)return ; vec[rt+sz].push_back(mp((rt<<1)+sz,0));vec[rt+sz].push_back(mp((rt<<1|1)+sz,0)); int mid=(l+r)>>1; built1(rt<<1,l,mid); built1(rt<<1|1,mid+1,r);}void addedge(int rt,int l,int r,int ql,int qr,int vul){ if(ql<=l&&r<=qr){ if(vul>0)vec[rt].push_back(mp(S,1)); else vec[S].push_back(mp(rt+sz,0)); return ; } int mid=(l+r)>>1; if(ql<=mid)addedge(rt<<1,l,mid,ql,qr,vul); if(qr>mid)addedge(rt<<1|1,mid+1,r,ql,qr,vul);}int dis[MAXN<<3];bool vis[MAXN<<3];queue
que;void spfa(int t){ for(int i=0;i<=S;i++)dis[i]=inf,vis[i]=0; que.push(t);vis[t]=1;dis[t]=dis[t+sz]=0; while(!que.empty()){ int t1=que.front();que.pop();vis[t1]=0; for(int i=0;i
dis[t1]+vec[t1][i].second){ dis[vec[t1][i].first]=dis[t1]+vec[t1][i].second; if(!vis[vec[t1][i].first]){vis[vec[t1][i].first]=1;que.push(vec[t1][i].first);} } } }}int main(){ scanf("%d%d%d",&n,&m,&p);S=(n<<3); sz=(n<<2);built(1,1,n);built1(1,1,n); int a,b,c,d; for(int i=1;i<=m;i++){ scanf("%d%d%d%d",&a,&b,&c,&d); S++; addedge(1,1,n,a,b,1);addedge(1,1,n,c,d,0); S++; addedge(1,1,n,c,d,1);addedge(1,1,n,a,b,0); } spfa(pos[p]); for(int i=1;i<=n;i++)printf("%d\n",dis[pos[i]+sz]);}

 

3073: [Pa2011]Journeys

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 634  Solved: 191
[][][]

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

转载于:https://www.cnblogs.com/wang9897/p/9479086.html

你可能感兴趣的文章
LVM快照(snapshot)备份
查看>>
绝望的第四周作业
查看>>
一月流水账
查看>>
数论四大定理
查看>>
npm 常用指令
查看>>
20几个正则常用正则表达式
查看>>
TextArea中定位光标位置
查看>>
非常棒的Visual Studo调试插件:OzCode 2.0 下载地址
查看>>
判断字符串在字符串中
查看>>
hdu4374One hundred layer (DP+单调队列)
查看>>
类间关系总结
查看>>
properties配置文件读写,追加
查看>>
Linux环境下MySql安装和常见问题的解决
查看>>
lrzsz——一款好用的文件互传工具
查看>>
ZPL语言完成条形码的打印
查看>>
这20件事千万不要对自己做!
查看>>
Linux环境下Redis安装和常见问题的解决
查看>>
玩转小程序之文件读写
查看>>
HashPump用法
查看>>
cuda基础
查看>>