• 牛客练习赛34 little w and Segment Coverage (差分区间)


    链接:https://ac.nowcoder.com/acm/contest/297/C
    来源:牛客网

    题目描述

    小w有m条线段,编号为1到m。

    用这些线段覆盖数轴上的n个点,编号为1到n。

    第i条线段覆盖数轴上的区间是L[i],R[i]。

    覆盖的区间可能会有重叠,而且不保证m条线段一定能覆盖所有n个点。

    现在小w不小心丢失了一条线段,请问丢失哪条线段,使数轴上没被覆盖到的点的个数尽可能少,请输出丢失的线段的编号和没被覆盖到的点的个数。如果有多条线段符合要求,请输出编号最大线段的编号(编号为1到m)。

    输入描述:

    第一行包括两个正整数n,m(1≤n,m≤10^5)。
    接下来m行,每行包括两个正整数L[i],R[i](1≤L[i]≤R[i]≤n)。

    输出描述:

    输出一行,包括两个整数a b。
    a表示丢失的线段的编号。
    b表示丢失了第a条线段后,没被覆盖到的点的个数。
    示例1

    输入

    复制
    5 3
    1 3
    4 5
    3 4

    输出

    复制
    3 0

    说明

    若丢失第1条线段,1和2没被线段覆盖到。
    若丢失第2条线段,5没被线段覆盖到。
    若丢失第3条线段,所有点都被线段覆盖到了。
    示例2

    输入

    复制
    6 2
    1 2
    4 5

    输出

    复制
    2 4

    说明

    若丢失第1条线段,1,2,3,6没被线段覆盖到。
    若丢失第2条线段,3,4,5,6没被线段覆盖到。

    题目大意:

    给你1..n长度的总区间,外加m条线段。问去掉哪条线段总区间未被覆盖的点最少。

    一开始用线段树的,T。然后看了官方题解。。:

    可以线段树,但是没必要。因为是先给出线段最后在做询问,所以可以用差分区间修改,最后 来一遍前缀和还原。

    然后记录数组中被线段仅仅覆盖 1 次的位置,将这些位置的权值标为 1,做一遍前缀和。

    然后答案就是 sum[r]-sum[l-1]这样,注意再加上一开始就没有被线段覆盖的点就好了。

    所以如果是最后再询问,那么可能就不太适合线段树来做了,毕竟差分区间是O(n)的,线段树常数还大。

    话说差分区间还真是个神奇的操作啊。也就是先保存每个点比之前那个点多覆盖的次数。

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <map>
    #include <set>
    typedef long long ll;
    const int mod=1000000007;
    const int inf=1000000000;
    const int maxn=100000;
    const int maxm=1000000;
    
    int left[maxn+10],right[maxn+10];
    int cov[maxn+10];
    int sum[maxn+10];
    
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        memset(cov,0,sizeof(cov));
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",left+i,right+i);
            cov[left[i]]++;
            cov[right[i]+1]--;
        }
        for(int i=1;i<=n;i++)
            cov[i]+=cov[i-1];
    
        int zero=0;
        for(int i=1;i<=n;i++)
        {
            if(cov[i]==0)
                zero++;
        }
    
        memset(sum,0,sizeof(sum));
        for(int i=1;i<=n;i++)
        {
            if(cov[i]==1)
                sum[i]=1;
        }
        for(int i=1;i<=n;i++)
            sum[i]+=sum[i-1];
    
        int ans=-1,uncov=inf;
        for(int i=m;i>=1;i--)
        {
            int temp=sum[right[i]]-sum[left[i]-1]+zero;
            if(temp<uncov)
            {
                ans=i;
                uncov=temp;
            }
        }
    
        printf("%d %d
    ",ans,uncov);
    
        return 0;
    }
    View Code
  • 相关阅读:
    eclipse.ini
    Windows8.1硬盘安装Ubuntu14.04双系统参考教程和多硬盘的注意事项[画画]
    【HTML+CSS】(1)基本语法
    Apache Curator获得真正的
    LVM逻辑卷管理@设备、格式、摩、引导自己主动安装一个完整的章节
    这么多的技术,作为一个freshman,什么研究?
    【JUnit4.10来源分析】0导航
    难度0 大写和小写交换
    java06
    java05
  • 原文地址:https://www.cnblogs.com/acboyty/p/10122686.html
Copyright © 2020-2023  润新知