zoukankan      html  css  js  c++  java
  • CodeForces-1175E Minimal Segment Cover

    题目描述

    现有(n)条线段,每条线段的左右端点为(L_i,R_i),保证(L_i le R_i).

    (m)个询问,每次查询(X_i,Y_i)区间内所有点被覆盖所需的线段的最小值。

    Input

    输入第一行包含两个整数(n,m),含义如上所述。

    接下来,有(n)行,每行有两个整数。

    (i+1)行包含(2)个整数,分别表示(L_i,R_i)

    接下来(m)行,表示(m)个询问。

    (1 le n,m le 2e5)

    (0 le L_i le R_i le 5e5)

    (0 le X_i le Y_i le 5e5)

    Output

    对于每个询问输出一个答案。

    若无法覆盖,输出(-1)即可。

    Sample Input

    2 3
    1 3
    2 4
    1 3
    1 4
    3 4
    
    3 4
    1 3
    1 3
    4 5
    1 2
    1 3
    1 4
    1 5
    

    Sample Output

    1
    2
    1
    
    1
    1
    -1
    -1
    

    利用倍增维护线段覆盖到的区间。

    首先,我们发现对于一个端点我们只用关心能覆盖它的线段最远能覆盖到哪里。

    对于每个左端点处理出用同一条线段最远的右端点。

    那么,覆盖的过程就是从左端点跳到最远的点,(Ans++),重复执行这个过程直到覆盖到右端点。

    如果暴力模拟,每次从一个段点跳到另一个端点,时间复杂度(O(n))

    仔细想想,我们发现这个过程和(LCA)的过程很像,于是我们就可以用倍增维护了。

    (Fa[i][j]) 表示用(1<<j)条线段,从(i)开始最远能覆盖到的点。

    代码如下

    #include <cstdio>
    #include <cstring>
    #include <map>
    #include <queue>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    #define int long long
    #define u64 unsigned long long
    #define Raed Read
    #define reg register
    #define debug(x) cerr<<#x<<" = "<<x<<endl;
    #define rep(a,b,c) for(reg int a=(b),a##_end_=(c); a<=a##_end_; ++a)
    #define ret(a,b,c) for(reg int a=(b),a##_end_=(c); a<a##_end_; ++a)
    #define drep(a,b,c) for(reg int a=(b),a##_end_=(c); a>=a##_end_; --a)
    #define erep(i,G,x) for(reg int i=(G).Head[x]; i; i=(G).Nxt[i])
    
    inline int Read() {
        int res = 0, f = 1;
        char c;
        while (c = getchar(), c < 48 || c > 57)if (c == '-')f = 0;
        do res = (res << 3) + (res << 1) + (c ^ 48);
        while (c = getchar(), c >= 48 && c <= 57);
        return f ? res : -res;
    }
    
    template<class T>inline bool Min(T &a, T const&b) {
        return a > b ? a = b, 1 : 0;
    }
    template<class T>inline bool Max(T &a, T const&b) {
        return a < b ? a = b, 1 : 0;
    }
    
    const int N = 2e5 + 5, M = 5e5 + 5, mod = 1e6 + 7;
    const int dx[5] = {1, -1, 0, 0, 0}, dy[5] = {0, 0, 0, 1, -1};
    const  double eps = 1e-6;
    
    int Fa[M][20], R[M];
    
    inline void _main(void) {
        int n = Read(), m = Raed();
        rep(i, 1, n) {
            int x = Raed(), y = Read();
            Max(R[x], y);
        }
        Fa[0][0] = R[0];
        rep(i, 1, M - 5)Max(R[i], R[i - 1]), Fa[i][0] = R[i];
        rep(j, 1, 19)rep(i, 0, M - 5)Fa[i][j] = Fa[Fa[i][j - 1]][j - 1];
        while (m--) {
            int Ans = 0, l = Raed(), r = Raed();
            drep(i, 19, 0)if (Fa[l][i] < r)l = Fa[l][i], Ans |= 1 << i;
            l = Fa[l][0];
            if (l < r)Ans = -1;
            else Ans++;
            printf("%d
    ", Ans);
        }
    }
    
    signed main() {
    #define offline1
    #ifdef offline
        freopen(".in", "r", stdin);
        freopen(".out", "w", stdout);
        _main();
        fclose(stdin); fclose(stdout);
    #else
        _main();
    #endif
        return 0;
    }
    
  • 相关阅读:
    winform中利用正则表达式得到有效的电话/手机号
    winform运行时如何接受参数?(示例)
    [基础]Javascript中的继承示例代码
    [转]C#中"is" vs "as"
    Javascript数组常用方法[包含MS AJAX.NET的prototype扩展方法]示例
    linq学习笔记(一)
    用winform应用程序登录网站的解决方案
    [转贴]操纵自如--页面内的配合与通信
    .net3.0中的扩展方法(示例)
    window.location或window.open如何指定target?
  • 原文地址:https://www.cnblogs.com/dsjkafdsaf/p/11259557.html
Copyright © 2011-2022 走看看