AtCoder Beginner Contest 177F - I hate Shortest Path Problem(求到达最短距离)

时间:2020-09-10 23:07:00   收藏:0   阅读:45

题:https://atcoder.jp/contests/abc177/tasks/abc177_f

题意:给定n和m,代表有(n+1)*m的矩阵,有n个询问,每个询问给定a和b,代表在第 i 行的第a列到第b列,不能进行向下操作,其余位置可以进行向下或向右操作,问在给定的限制中,从第1行的任意位置走到第i+1行的最短距离是多少或输出-1表示不能到达。

分析:对于每个位置的答案,我们建立线段树来记录答案。考虑某个位置pos的答案,肯定是从上一行的左边的某个位置sta能够整体地向右移动pos-sta,再向下移动一个单位,同时保证移动到pos位置是最小的。

   因为这个最小还与位置有关,所以我们再建一棵关于ansi-i的线段树;

   我们可以发现,若能得到终点是a~b的路径,那么答案肯定有比这些路径还小的答案,(a以前),所以每次就把a~b的位置加上无穷大,代表不会取到,其次,若1~b能够到达下一行的b+1~n,那么只需更新b+1位置即可,因为后面位置若通过此方法进行移动,肯定比b+1位置大,所以不用更新。

   最后整体加上1表示向下移动了一步

技术图片
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
const int M=2e5+5;
const int inf=0x3f3f3f3f;
const ll INF=1e18;
struct Segtree{
    ll tr[M<<2],lz[M<<2];
    void build(int root,int l,int r){
        tr[root]=0,lz[root]=0;
        if(l==r)
            return ;
        int midd=(l+r)>>1;
        build(lson);
        build(rson);
    }
    void pushdown(int root){
        ll c=lz[root];
        tr[root<<1]+=c,tr[root<<1|1]+=c;
        lz[root<<1]+=c,lz[root<<1|1]+=c;
        lz[root]=0;
    }
    void update(int L,int R,ll val,int root,int l,int r){
        if(L<=l&&r<=R){
            tr[root]+=val;
            lz[root]+=val;
            return ;
        }
        if(lz[root])
            pushdown(root);
        int midd=(l+r)>>1;
        if(L<=midd)
            update(L,R,val,lson);
        if(R>midd)
            update(L,R,val,rson);
        tr[root]=min(tr[root<<1],tr[root<<1|1]);
    }
    ll query(int L,int R,int root,int l,int r){
        if(L<=l&&r<=R){
            return tr[root];
        }
        if(lz[root])
            pushdown(root);
        ll res=INF;
        int midd=(l+r)>>1;
        if(L<=midd)
            res=min(res,query(L,R,lson));
        if(R>midd)
            res=min(res,query(L,R,rson));
        return res;
    }
}x,y;
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    x.build(1,1,m),y.build(1,1,m);
    for(int i=1;i<=m;i++)
        y.update(i,i,-i,1,1,m);
    for(int i=1;i<=n;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        ///b+1
        x.update(b+1,b+1,min(1ll*(b+1+y.query(1,b,1,1,m))-x.query(b+1,b+1,1,1,m),0ll),1,1,m);
        y.update(b+1,b+1,min(y.query(1,b,1,1,m)-y.query(b+1,b+1,1,1,m),0ll),1,1,m);
        ///a~b
        x.update(a,b,1e9,1,1,m);
        y.update(a,b,1e9,1,1,m);
        ///向下
        x.update(1,m,1,1,1,m);
        y.update(1,m,1,1,1,m);
        ll ans=x.query(1,m,1,1,m);
        if(ans>=1e9)
            puts("-1");
        else
            printf("%lld\n",ans);
    }
    return 0;
}
View Code

 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!