zoukankan      html  css  js  c++  java
  • 【Atcoder Beginner Contest 177 】 F

    AtCoder Beginner Contest 177 F - I hate Shortest Path Problem

    题意

    给出一个高为 n+1,宽为 m 的矩形格子。现在你可以选择第一行的任意一个位置为起点,开始移动,只能向右或者下移动。在 [1,n] 行每行都有一个区间[l,r],在这个区间中,不能向下移动。

    问到达第[2,n+1]行的最少移动次数。

    思路

    参考博客:
    https://www.cnblogs.com/Go7338395/p/13591270.html

    https://blog.csdn.net/qq_45323960/article/details/108302036

    因为到达某一行,向下移动的次数是固定的,所以我们先看向右移动的次数,定义 dis[i][x] 表示到达第 i 行,第 x 个格子的最小步数。

    初始化 dis[1][1,2,3,...,m] 为0。

    这时我们来看,对于当前格子最好的走法,肯定是如果能向下走,直接向下走,否则向右走直到可以向下走,然后向下走。

    来看具体过程。
    假如现在在第4行,dis[4]为:

    0 1 2 0 0 0

    这一行的话,如果是区间[4,5]不能向下走。

    那么第 5 行的第4,5列应该是从第5行的第3列走过去。

    那么我们就要更新[4,5]这段区间为以 dis[ 3 ]+1 为开头的公差为 1 的数列。

    具体一些:
    如果第 i 行最小可以到达的列数为 now,那么我们看,如果第 i 行不可以向下走的区间为[l,r]。

    1. l<=now && now <=r ,第i+1行可以到达的最小列数为 r+1,这时更新dis[i+1][now---r]为无穷大。

    2. 当now < l的时候,我们就更新[l,r] 为以dis[i][l-1]+1为首项公差为1的数列。

    3. dis[i+1]的最小值+ i 就是答案。

    对于更改操作,使用线段树。

    具体可以看代码

    /*
     * @Autor: valk
     * @Date: 2020-07-17 18:36:08
     * @LastEditTime: 2020-09-25 16:31:41
     * @Description: 如果邪恶  是华丽残酷的乐章 它的终场 我会亲手写上 晨曦的光 风干最后一行忧伤 黑色的墨 染上安详
    */
    #include <algorithm>
    #include <iostream>
    #include <map>
    #include <math.h>
    #include <queue>
    #include <set>
    #include <stack>
    #include <stdio.h>
    #include <string.h>
    #include <string>
    #include <vector>
    #define emplace_back push_back
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int mod = 1e9 + 7;
    const int seed = 12289;
    const double eps = 1e-6;
    const int inf = 0x3f3f3f3f;
    const int N = 1e6 + 10;
    
    struct note {
        int tag, minn;//minn表示当前区间的最小值,tag 表示当前区间[l,r]是一个以tag 为首项的公差为1的等差数列。
    } node[N * 4];
    
    void build(int rt, int l, int r)
    {
        if (l == r)
            return;
        int mid = (l + r) >> 1;
        build(rt * 2, l, mid);
        build(rt * 2 + 1, mid + 1, r);
    }
    
    void pushdown(int rt, int l, int r)
    {
        if (!node[rt].tag) {
            return;
        }
        int mid = (l + r) >> 1;
        node[rt * 2].tag = node[rt].tag;
        node[rt * 2 + 1].tag = node[rt].tag + mid - l + 1;
        node[rt * 2].minn = node[rt].tag;
        node[rt * 2 + 1].minn = node[rt * 2 + 1].tag;
        node[rt].tag = 0;
    }
    
    void update(int rt, int l, int r, int qs, int qe, int val)
    {
        if (qs <= l && qe >= r) {
            node[rt].minn = node[rt].tag = val;
            return;
        }
        pushdown(rt, l, r);
        int mid = (l + r) / 2;
        if (qs <= mid)
            update(rt * 2, l, mid, qs, qe, val);
        if (qe > mid)
            update(rt * 2 + 1, mid + 1, r, qs, qe, val + max(0, mid - max(qs, l) + 1));//这里注意考虑查询区间和当前区间的相交情况,来递归转移
        node[rt].minn = min(node[rt * 2].minn, node[rt * 2 + 1].minn);
    }
    
    int query(int rt, int l, int r, int pos)
    {
        if (l == r) {
            return node[rt].minn;
        }
        pushdown(rt, l, r);
        int mid = (l + r) / 2;
        if (pos <= mid) {
            return query(rt * 2, l, mid, pos);
        } else {
            return query(rt * 2 + 1, mid + 1, r, pos);
        }
    }
    
    int main()
    {
        int n, m;
        scanf("%d%d", &n, &m);
        build(1, 1, m);
        int now = 1;
        for (int i = 1; i <= n; i++) {
            int l, r;
            scanf("%d%d", &l, &r);
            if (now < l) {
                update(1, 1, m, l, r, query(1, 1, m, l - 1) + 1);
            } else if (l <= now && now <= r) {
                update(1, 1, m, now, r, 1000000);
                now = r + 1;
            }
            int ans = node[1].minn;
            if (ans >= m) {
                printf("-1
    ");
            } else {
                printf("%d
    ", ans + i);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    人机猜拳
    M1分数分配
    postmortem report of period M1
    视频文档分享网站场景测试说明书
    功能规格说明书
    11.9Daily Scrum
    11.6Daily Scrum
    需求博客
    11.5Daily Scrum
    11.3Daily Scrum
  • 原文地址:https://www.cnblogs.com/valk3/p/13731117.html
Copyright © 2011-2022 走看看