hihocoder 1079 离散化(线段树+区间离散化)

题意:

区间总长为L,依次给n个子区间,后面的覆盖前面的,求最后没有被完全盖住的子区间个数。

离散化:维护区间端点的相对大小关系,将其map到[1, 2n]的区间上。

注意:map之后得到的是端点,而线段树上的节点是单位长度的区间,所以在update的时候应该 update(l, r-1)。。。

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <string>
#include <cstring>
#include <vector>
#include <list>
#include <queue>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
using namespace std;

#define rep(i, s, t) for(int (i)=(s);(i)<=(t);++(i))
#define urep(i, s, t) for(int (i)=(s);(i)>=(t);--(i))

typedef long long LL;

const int inf  = 0x7fffffff;
const int Maxn = (int)1e5+10;

int li[Maxn], ri[Maxn];
int vis[Maxn];
int n, L;

const int Maxnode = Maxn<<2;
int color[Maxnode];
#define lson(x) ((x)<<1)
#define rson(x) (((x)<<1)|1)
struct SegmentTree {
    int length, qL, qR;
    void init(int n) {
        length = n;
        memset(color, -1, sizeof(color));
    }

    void query(int L, int R) {
        qL = L;
        qR = R;
        _query(1, 1, length);
    }

    void _query(int o, int L, int R) {
        if (color[o] != -1) {
            vis[color[o]] = 1;
        } else {
            if (L == R) return;
            int M = (L+R)>>1;
            int lc = lson(o), rc = rson(o);
            if (qL <= M)
                _query(lc, L, M);
            if (qR > M)
                _query(rc, M+1, R);
        }
    }

    void Set(int L, int R, int v) {
        qL = L;
        qR = R;
        _set(1, 1, length, v);
    }

    void _set(int o, int L, int R, int v) {
        if (qL <= L && qR >= R) {
            color[o] = v;
        } else {
            pushdown(o, L, R);
            int M = (L+R)>>1;
            int lc = lson(o), rc = rson(o);
            if (qL <= M)
                _set(lc, L, M, v);
            if (qR > M)
                _set(rc, M+1, R, v);
        }
    }

    void pushdown(int o, int L, int R) {
        if (color[o] != -1) {
            int lc = lson(o), rc = rson(o);
            color[lc] = color[rc] = color[o];
            color[o] = -1;
        }
    }
};

SegmentTree tree;

int x[Maxn+5];

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.in", "r", stdin);
#endif
    while (scanf("%d%*d", &n) != EOF) {
           if (n == 0) {cout << 0 << endl;continue;}
            int cnt = 0;
            rep(i, 1, n) {
                scanf("%d%d", li+i, ri+i);
                x[cnt++] = li[i];
                x[cnt++] = ri[i];
            }
            sort(x, x+cnt);
            cnt = unique(x, x+cnt) - x;
            tree.init(cnt);
            rep(i, 1, n) {
                int a = lower_bound(x, x+cnt, li[i])-x+1, b = lower_bound(x, x+cnt, ri[i])-x;
                if (a <= b)
                    tree.Set(a, b, i);
                //cout << "map: " << a << ' ' << b << endl;
            }
            tree.query(1, cnt);
            int ans = 0;
            rep(i, 1, n)
                if (vis[i]) ++ans;
            printf("%d\n", ans);
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值