AcWing 4195. 線段覆蓋(離散化+差分)


AcWing 4195. 線段覆蓋(離散化+差分)

原題鏈接

題目描述

在一個坐標軸上有 \(n\) 條線段。

每條線段的每個端點的坐標都為整數。

可能存在退化成點的線段。

線段之間可以相互交叉、嵌套甚至重合。

請你計算,對於每個 \(k \in\{1,2, \ldots, n\}\) ,坐標軸中共有多少個整數坐標的點滿足恰好被 \(k\) 條線段覆蓋。
注意,左右端點分別為 \(l_{i}, r_{i}\) 的線段覆蓋點 \(x\) 當且僅當 \(l_{i} \leq x \leq r_{i}\)

輸入格式

第一行包含整數 \(n\)

接下來 \(n\) 行,每行包含兩個整數 \(l\_i,r\_i\),表示一條線段的左右端點。

輸出格式

一行 \(n\) 個整數,其中第 \(i\) 個整數表示坐標軸中滿足恰好被 \(i\) 條線段覆蓋的整數坐標的點的數量。

數據范圍

前三個測試點滿足 \(1 \leq n \leq 3\)
所有測試點滿足 \(1 \leq n \leq 2 \times 10^{5}, 0 \leq l_{i} \leq r_{i} \leq 10^{18}\)

輸入樣例1:

3
0 3
1 3
3 8

輸出樣例1:

6 2 1

輸入樣例2:

3
1 3
2 4
5 7

輸出樣例2:

5 2 0

算法

差分數組,對於第一個樣例:

image-20211212135432568

朴素做法如上,對於所有的點差分求前綴和即可,但是發現只要保存左右端點消息即可,端點和端點之間的點被線段覆蓋的條數一定是一樣的。

map做法:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>

using namespace std;

typedef long long LL;

const int N = 200010;

map<LL, int> b;
LL ans[N];

int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i ++ )
    {
        LL l, r;
        scanf("%lld%lld", &l, &r);
        b[l] ++, b[r + 1] -- ;
    }

    LL sum = 0, last = -1;
    for (auto& [k, v]: b)
    {
        if (last != -1) ans[sum] += k - last;
        sum += v;
        last = k;
    }

    for (int i = 1; i <= n; i ++ )
        printf("%lld ", ans[i]);

    return 0;
}

離散化后差分:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N =  1000010;
LL l[N], r[N], res[N], x[N];
vector<LL> all;
int n, m;
int main()
{
	scanf("%d", &n);
	for(int i = 0; i < n; i++)
	{
        scanf("%lld%lld", &l[i], &r[i]);
        r[i]++;   
        all.push_back(l[i]);
        all.push_back(r[i]);
	}
	
	
	sort(all.begin(), all.end());
	all.erase(unique(all.begin(), all.end()), all.end());
	m = all.size();
	
	for(int i = 0 ; i < n; i++)
	{
        int pos1 = lower_bound(all.begin(), all.end(), l[i]) - all.begin();
        int pos2 = lower_bound(all.begin(), all.end(), r[i]) - all.begin();
        x[pos1]++;
        x[pos2]--;
	}
	LL sum = 0;
	for(int i = 0; i < m; i++){
	    if(i != 0){
	        res[sum] += all[i] - all[i - 1];
	    }
	    sum += x[i];
	}
    
    for(int i = 1; i <= n; i++)
        cout<<res[i]<<" ";
    
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM