zoukankan      html  css  js  c++  java
  • AT [ABC177F] I hate Shortest Path Problem

    因为每行只有一个区域不能往下走,因此我们可以来分析一下从起点到整个矩形每个位置的最短路。可以发现每一行的最短路只与上一行的最短路有关,假设我们知道上一行的最短路,上一行不能往下走的区间在 ([L, R]),那么可以发现的是 ([1, L - 1], [R + 1, m]) 这些区间会直接从上一行走下来,因为假设存在一个更靠前的位置它走过来更优,那么前一行的最短路就会由这个位置走过来更新。同理,因为区间 ([L, R]) 是不能从上面直接走下来的,所以其一定是从 ([1, L - 1]) 的某个位置开始走然后走完整段区间,根据前面的理论,这个开始的点应该是 (L - 1) 这个位置。

    于是我们每行最短路的变化就很清楚了,相当于将 ([L, R]) 填上一段长度以 (dis_{L - 1} + 1) 开头的公差为 (1) 的等差数列,然后再整体加 (1)(因为所有点都需要向下走)。这个整体加 (1) 的操作可以直接处理,于是我们需要寻找到一种方法能将区间填上一段等差数列。

    可以发现线段树是一个很好的选择,对于每个区间,我们维护这个区间的最小值,以及这个区间如果为(否则为 (0))等差数列时的开头数字(也是懒标记)。那么我们每次修改之前只需要提前下方完所有懒标记,然后再修改就没有错了。因为我们在提前下方懒标记时会保证当前添加的懒标记在后续下方时会最后下放,也就是作为最终覆盖。

    一些坑点

    • 修改时递归右区间等差数列的开头元素一定要想清楚是什么。
    #include<bits/stdc++.h>
    using namespace std;
    #define ls (p << 1)
    #define rs (p << 1 | 1)
    #define mid (l + r) / 2
    #define rep(i, l, r) for(int i = l; i <= r; ++i)
    typedef long long ll;
    const int N = 1200000 + 5;
    struct tree{
        int min, tag;
    }t[N];
    int n, m, a, b, fir;
    int read(){
        char c; int x = 0, f = 1;
        c = getchar();
        while(c > '9' || c < '0'){ if(c == '-') f = -1; c = getchar();}
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    void lazy(int p, int k){
        t[p].min = t[p].tag = k;
    }
    void down(int p, int l, int r){
        if(!t[p].tag) return;
        lazy(ls, t[p].tag), lazy(rs, t[p].tag + mid - l + 1);
        t[p].tag = 0;
    }
    void update(int p, int l, int r, int x, int y, int k){
        down(p, l, r);
        if(l >= x && r <= y){ lazy(p, k); return;}
        if(mid >= x) update(ls, l, mid, x, y, k);
        if(mid < y) update(rs, mid + 1, r, x, y, k + max(0, mid - max(l, x) + 1));
        t[p].min = min(t[ls].min, t[rs].min);
    }
    int query(int p, int l, int r, int x, int y){
        if(l >= x && r <= y) return t[p].min;
        down(p, l, r);
        if(mid >= x) return query(ls, l, mid, x, y);
        else return query(rs, mid + 1, r, x, y);
    }
    int main(){
        n = read(), m = read();
        rep(i, 1, n){
            a = read(), b = read(); 
            fir = (a == 1 ? m + 1 : query(1, 1, m, a - 1, a - 1) + 1);
            update(1, 1, m, a, b, fir);
            printf("%d
    ", t[1].min >= m + 1 ? -1 : t[1].min + i);
        }
        return 0;
    }
    
    GO!
  • 相关阅读:
    多线程与多进程
    网络编程----socketserver多并发实现、FTP上传多并发、udp协议套接字多并发
    网络编程----粘包以及粘包问题的解决、FTP上传
    网络编程----socket介绍、基于tcp协议的套接字实现、基于udp协议的套接字实现
    python基础----软件目录结构规范
    python基础----模块、包
    python基础----异常处理
    python基础----常用模块
    python基础----再看property、描述符(__get__,__set__,__delete__)
    python基础---- __getattribute__----__str__,__repr__,__format__----__doc__----__module__和__class__
  • 原文地址:https://www.cnblogs.com/Go7338395/p/13591270.html
Copyright © 2011-2022 走看看