zoukankan      html  css  js  c++  java
  • AGC 015 E

    E - Mr.Aoki Incubator

    链接

    题意:

      数轴上有N个黑点,每个点都有一个方向向右的正速度v。当两个点在同一个位置上重合时,若其中一个是红色,另一个也变成红色。保证没有相同速度或初始坐标。现问你有多少方法染红一些点,使得无穷久后所有点都被染红。 N≤200000

    分析:

       首先按照速度v从大到小排序,对于一个点,它左边的点中,坐标x第一个比它的坐标小的,设为L;右边的点中,坐标最后一个比它的坐标大的,设为R。

      那么如果这个点被染色,R-L+1区间的点都将被染色,预处理出每个点对应的区间。问题变成选一些区间,覆盖1到n的问题,dp一下。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<cctype>
    #include<set>
    #include<queue>
    #include<vector>
    #include<map>
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 200005, mod = 1e9 + 7;
    int F[N], sum[N], mn[N], mx[N];
    struct Edge{ int v, l, r, x; } A[N];
    bool cmp1(const Edge &A,const Edge &B) { return A.v > B.v; }
    bool cmp2(const Edge &A,const Edge &B) { return A.l == B.l ? A.r < B.r : A.l < B.l; } // 左端点相同时的排序!!! 
    
    int main() {
        int n = read();
        for (int i = 1; i <= n; ++i) 
            A[i].x = read(), A[i].v = read();
        sort(A + 1, A + n + 1, cmp1);
            
        mn[1] = A[1].x;
        for (int i = 2; i <= n; ++i) mn[i] = min(mn[i - 1], A[i].x);
        for (int i = 1; i <= n; ++i) {
            int l = 1, r = i - 1, p = i;
            while (l <= r) {
                int mid = (l + r) >> 1;
                if (mn[mid] < A[i].x) p = mid, r = mid - 1;
                else l = mid + 1;
            }
            A[i].l = p;
        }
        mx[n] = A[n].x;
        for (int i = n - 1; i >= 1; --i) mx[i] = max(mx[i + 1], A[i].x);
        for (int i = n; i >= 1; --i) {
            int l = i + 1, r = n, p = i;
            while (l <= r) {
                int mid = (l + r) >> 1;
                if (mx[mid] > A[i].x) p = mid, l = mid + 1;
                else r = mid - 1;
            }
            A[i].r = p;
        }
        sort(A + 1, A + n + 1, cmp2);
        int p = 1, Ans = 0;
        for (int i = 1; i <= n; ++i) {
            while (A[p].r < A[i].l - 1) 
                p ++;
            F[i] = (sum[i - 1] - sum[p - 1] + mod) % mod;
            if (A[i].l == 1) F[i] = (F[i] + 1) % mod;
            sum[i] = (sum[i - 1] + F[i]) % mod;
            if (A[i].r == n) Ans = (Ans + F[i]) % mod;
        }
        cout << Ans;
        return 0;
    }
  • 相关阅读:
    php基础的一点注意事项
    每天学习一点点--word-break和word-wrap用法和区别
    line-height的一点粗浅认识
    图片的无缝滚动效果
    CSS篇章
    redis 3.0 集群__数据迁移和伸缩容
    redis 3.0 集群__使用
    官方教程文档地址
    redis 3.0 集群__安装
    java 泛型的使用
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10337610.html
Copyright © 2011-2022 走看看