1. 程式人生 > >牛客練習賽34 little w and Segment Coverage (差分割槽間)

牛客練習賽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\n",ans,uncov);

    return 0;
}
View Code