Board Game(线段树 bfs)

http://codeforces.com/problemset/problem/605/D

题意:

给出n个点, ( a , b , c , d ) (a,b,c,d) ,你有两个值 ( x , y ) (x,y) ,当一个点的 a x b y a\leq x\bigwedge b\leq y ,你可以到达这个点,并且 x c , y d x\to c,y\to d 。问到达最后一个点的最短路径。初始时 x = 0 , y = 0 x=0,y=0

解析:

a , c a,c 值离散化作为下标开线段树,每个点将 b b 塞入 a a 点对应的 s e t set

假设我当前在 x , y x,y ,那么我在 [ 1 , x ] [1,x] 的区间集合中,找小于等于 b b 的点,进行更新即可。更新规则使用bfs,保证每个搜到的点都是最短路。所以我们要在找到一个点后从线段树中删除对应的节点。

由于我使用的是pair(second存id),所以找小于等于 b b 的,使用 l o w e r _ b o u n d ( { b + 1 , 1 } ) lower\_bound(\{b+1,-1\}) 找到上届之上的位置。

注意线段树子区间和夫区间的删除。

代码:

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define fi first
#define se second
const int maxn=1e5+9;

struct node{
    int a,b,c,d,id;
}e[maxn];
int pre[maxn];

int U[maxn*2],num;
#define pill pair<int,int>
set<pill>tr[maxn<<3];

#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid (l+r>>1)
void update(int rt,int l,int r,int p,pill val){
    tr[rt].insert(val);
    if(l==r)return;
    if(p<=mid)update(ls,l,mid,p,val);
    else update(rs,mid+1,r,p,val);
}

set<pill> query(int rt,int l,int r,int L,int R,pill val){ //val=[b+1,-1]
    set<pill>res;
    if(l>=L&&r<=R){
        if(tr[rt].empty())return res;
        auto it=tr[rt].lower_bound(val);
        if(it==tr[rt].begin())return res;
        auto it2=tr[rt].begin();
        while(it2!=it){
            res.insert(*it2);
            it2++;
        }
        tr[rt].erase(tr[rt].begin(),it);
        if(l!=r&&res.size()){
            query(ls,l,mid,L,R,val);
            query(rs,mid+1,r,L,R,val);
        }
        return res;
    }
    if(L<=mid)res=query(ls,l,mid,L,R,val);
    if(R>mid){
        auto tmp=query(rs,mid+1,r,L,R,val);
        for(auto P:tmp)res.insert(P);
    }
    for(auto P:res)tr[rt].erase(P);
    return res;
}

void bfs(){
    queue<pair<int,pill>>Q;
    Q.push({lower_bound(U+1,U+1+num,0)-U,{0,-1}}); //a b id
    while(!Q.empty()){
        auto P=Q.front();
        Q.pop();
        pill fin={P.se.fi+1,-1};
        auto res=query(1,1,num,1,P.fi,fin);
        for(auto T:res){
            pre[T.se]=P.se.se;
            Q.push({e[T.se].c,{e[T.se].d,T.se}});
        }
    }
}

int main(){
    int n;scanf("%d",&n);
    rep(i,1,n){
        scanf("%d%d%d%d",&e[i].a,&e[i].b,&e[i].c,&e[i].d);
        e[i].id=i;
        U[++num]=e[i].a;
        U[++num]=e[i].c;
    }
    U[+num]=0;
    sort(U+1,U+1+num);
    num=unique(U+1,U+1+num)-U-1;
    rep(i,1,n){
        e[i].a=lower_bound(U+1,U+1+num,e[i].a)-U;
        e[i].c=lower_bound(U+1,U+1+num,e[i].c)-U;
    }
    rep(i,1,n){
        update(1,1,num,e[i].a,{e[i].b,e[i].id});
    }
    bfs();
    if(pre[n]==0)return 0*printf("-1\n");
    stack<int>S;
    int now=n;
    do{
        S.push(now);
        now=pre[now];
    }while(now>0);
    printf("%d\n",S.size());
    while(!S.empty()){
        printf("%d ",S.top());S.pop();
    }
}

发布了723 篇原创文章 · 获赞 314 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/103161930
今日推荐