BZOJ3073 PA2011Journeys(线段树+bfs)

  线段树优化建图裸题。建两棵线段树,一棵表示入一棵表示出。对题中所给的边新建一个虚拟点,将两段区间拆成线段树上对应区间,出线段树中对应区间所表示的点向虚拟点连边权0的边,虚拟点向入线段树中对应区间所表示的点连边权1的边;线段树上的点之间连边权0的边(表示入的由父亲连向儿子,表示出的由儿子连向父亲),表示相同点的叶子节点(由入连向出)之间连边权0的边。01bfs即可。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define ll long long
#define N 500010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,m,S,id[2][N],root[2],v[2][100],p[N*10],d[N*10],t,cnt;
struct data{int to,nxt,len;
}edge[N<<5];
struct data2{int l,r;
}tree[2][N<<3];
deque<int> q;
void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;}
void build(int &k,int l,int r,int p)
{
    k=++cnt;
    if (l==r) {id[p][l]=k;return;}
    int mid=l+r>>1;
    build(tree[p][k].l,l,mid,p);
    build(tree[p][k].r,mid+1,r,p);
    if (p==0) addedge(tree[p][k].l,k,0),addedge(tree[p][k].r,k,0);
    else addedge(k,tree[p][k].l,0),addedge(k,tree[p][k].r,0);
}
void find(int &k,int l,int r,int x,int y,int p)
{
    if (l==x&&r==y) {v[p][++v[p][0]]=k;return;}
    int mid=l+r>>1;
    if (y<=mid) find(tree[p][k].l,l,mid,x,y,p);
    else if (x>mid) find(tree[p][k].r,mid+1,r,x,y,p);
    else find(tree[p][k].l,l,mid,x,mid,p),find(tree[p][k].r,mid+1,r,mid+1,y,p);
}
void bfs(int S)
{
    d[S]=0;q.push_back(S);
    while (!q.empty())
    {
        int x=q.front();q.pop_front();
        for (int i=p[x];i;i=edge[i].nxt)
        if (d[x]+edge[i].len<d[edge[i].to])
        {
            d[edge[i].to]=d[x]+edge[i].len;
            if (edge[i].len) q.push_back(edge[i].to);
            else q.push_front(edge[i].to);
        }
    }
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("bzoj3073.in","r",stdin);
    freopen("bzoj3073.out","w",stdout);
    const char LL[]="%I64d\n";
#else
    const char LL[]="%lld\n";
#endif
    n=read(),m=read(),S=read();
    build(root[0],1,n,0);
    build(root[1],1,n,1);
    for (int i=1;i<=m;i++)
    {
        int a=read(),b=read(),c=read(),d=read();
        v[0][0]=v[1][0]=0;cnt++;
        find(root[0],1,n,a,b,0);
        for (int x=1;x<=v[0][0];x++) addedge(v[0][x],cnt,0);
        find(root[1],1,n,c,d,1);
        for (int x=1;x<=v[1][0];x++) addedge(cnt,v[1][x],1);
        v[0][0]=v[1][0]=0;cnt++;
        find(root[0],1,n,c,d,0);
        for (int x=1;x<=v[0][0];x++) addedge(v[0][x],cnt,0);
        find(root[1],1,n,a,b,1);
        for (int x=1;x<=v[1][0];x++) addedge(cnt,v[1][x],1);
    }
    for (int i=1;i<=n;i++) addedge(id[1][i],id[0][i],0);
    memset(d,42,sizeof(d));bfs(id[0][S]);
    for (int i=1;i<=n;i++) printf("%d\n",d[id[0][i]]);
    return 0;
}

 

posted @ 2018-11-05 00:00  Gloid  阅读(178)  评论(0编辑  收藏  举报