POJ 2528 Mayor's posters 线段树 区间更新 + 简单哈希函数

区间维护是否被覆盖

贴代码(AC,110ms)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
using namespace std;
const int MAX = 1e5 + 50;
bool peo[MAX];
int mark[MAX < 2], cnt, h[MAX * 3];
int lt[MAX], rt[MAX];

void pushDown(int rt){
    if(mark[rt] != -1){
        mark[rt << 1] = mark[rt << 1 | 1] = mark[rt];
        mark[rt] = -1;
    }
}

void update(int qL, int qR, int p, int l, int r, int rt){
    if(qL <= l && r <= qR){
        mark[rt] = p;
        return;
    }
    pushDown(rt);
    int m = (l + r) >> 1;
    if(qL <= m)
        update(qL, qR, p, lson);
    if(m < qR)
        update(qL, qR, p, rson);
}

void query(int l, int r, int rt){
    if(mark[rt] != -1){
        if(!peo[mark[rt]])
            cnt++;
        peo[mark[rt]] = true;
        return;
    }
    if(l == r)
        return;
    int m = (l + r) >> 1;
    query(lson);
    query(rson);
}

int hash(int key, int n){
    int l = 0, r = n - 1;
    while(l <= r){
        int m = (l + r) >> 1;
        if(key == h[m])
            return m;
        if(key > h[m])
            l = m + 1;
        else
            r = m - 1;
    }
    return -1;
}

int main(){
    int ca, n, m, len, a, b;
    scanf("%d", &ca);
    while(ca--){
        memset(mark, -1, sizeof(mark));
        memset(peo, false, sizeof(peo));
        scanf("%d", &n);
        m = 0, len = 1, cnt = 0;
        for(int i = 0; i < n; ++i){
            scanf("%d%d", lt + i, rt + i);
            h[m++] = lt[i], h[m++] = rt[i];
        }
        sort(h, h + m);
        for(int i = 1; i < m; ++i)
            if(h[i] != h[i - 1])
                h[len++] = h[i];
        for(int i = len - 1; i > 0; --i){
            if(h[i] != h[i - 1] + 1)
                h[len++] = h[i - 1] + 1;
        }
        sort(h, h + len);
        for(int i = 0; i < n; ++i){
            a = hash(lt[i], len);
            b = hash(rt[i], len);
            update(a + 1, b + 1, i, 1, len , 1);
        }
        query(1, len, 1);
        printf("%d\n", cnt);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值