天天看點

Luogu 2082 區間覆寫(加強版)

題目連結:​​傳送門​​

題目描述

已知有N個區間,每個區間的範圍是[si,ti],請求出區間覆寫後的總長。

輸入格式:

N s1 t1 s2 t2 …… sn tn

輸出格式:

共一行,一個正整數,為覆寫後的區間總長。

輸入樣例

3

1 100000

200001 1000000

100000000 100000001

輸出樣例

900002

說明

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <complex>
#include <algorithm>
#include <climits>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define
#define

using namespace std;
typedef long long ll;
struct node {
    ll l, r;
    mutable ll v;
    node (ll L = 0, ll R = -1, ll V = 0) : l(L), r(R), v(V) {}
    bool operator < (const node &a)const {
        return l < a.l;
    }
};
set<node> s;
int n;
ll l, r;
#define
iter split(ll pos) {
    iter it = s.lower_bound(node(pos));
    if (it != s.end() and it->l == pos) return it;
    --it;
    ll l = it->l, r = it->r, val = it->v;
    s.erase(it);
    s.insert(node(l, pos - 1, val));
    return s.insert(node(pos, r, val)).first;
}
void assign(ll l, ll r) {
    iter rrc = split(r + 1), llc = split(l);
    s.erase(llc, rrc);
    s.insert(node(l, r, 1LL));
}
ll ask(ll l, ll r) {
    iter llc = split(l), rrc = split(r + 1);
    ll ans = 0;
    for (; llc != rrc; llc++)
      if (llc->v) //覆寫掉的就加上
        ans += llc->r - llc->l + 1;
    return ans;
}

int main() {
    scanf("%d", &n);
    s.insert(node(0, ll(1e17 + 2), 0)); //初始節點
    for (int i = 1; i <= n; i++) {
        scanf("%lld%lld", &l, &r);
        assign(l, r);
    }
    printf("%lld\n", ask(0, 1e17));
}      

繼續閱讀