1. 程式人生 > >牛客網 - little w and Segment Coverage(區間覆蓋問題)

牛客網 - little w and Segment Coverage(區間覆蓋問題)

題目連結:https://ac.nowcoder.com/acm/contest/297/C
時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 262144K,其他語言524288K
64bit IO Format: %lld

題目描述

小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條線段後,沒被覆蓋到的點的個數。

輸入

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

輸出

3 0
2 4

說明

樣例1:
若丟失第1條線段,1和2沒被線段覆蓋到。
若丟失第2條線段,5沒被線段覆蓋到。
若丟失第3條線段,所有點都被線段覆蓋到了。
樣例2:
若丟失第1條線段,1,2,3,6沒被線段覆蓋到。
若丟失第2條線段,3,4,5,6沒被線段覆蓋到。

解題思路

我們可以先求出那些沒有被覆蓋的長度,然後再求出那些覆蓋長度為1的最長的那一段。

#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
struct edge {
    int l, r, t;
}e[100010];
int main()
{
    int n, k, m, sum, ans[100010];
    while (~scanf("%d%d", &n, &m))
    {
        k = sum = 0;
        memset(ans, 0, sizeof(ans));
        for (int i = 0; i < m; i++)
        {
            scanf("%d%d", &e[i].l, &e[i].r);
            ans[e[i].l]++;
            ans[e[i].r + 1]--;
        }
        for (int i = 1; i <= n; i++)
            ans[i] += ans[i - 1];
        for (int i = 1; i <= n; i++)
        {
            if (!ans[i])
                sum++;
            ans[i] = !(ans[i] - 1);
            ans[i] += ans[i - 1];
        }
        for (int i = 1; i < m; i++)
            if (ans[e[i].r] - ans[e[i].l - 1] <= ans[e[k].r] - ans[e[k].l - 1])
                k = i;
        printf("%d %d\n", k + 1, ans[e[k].r] - ans[e[k].l - 1] + sum);
    }
    return 0;
}