线段树+离散化问题

线段树+离散化的问题。


Mayor’s posters

题目传送:POJ - 2528 - Mayor’s posters

参考胡浩的写法。

AC代码:

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <sstream>
#include <utility>
#include <iostream>
#include <algorithm>
#include <functional>
#define LL long long
#define INF 0x7fffffff
using namespace std;

const int maxn = 12345;
bool Hash[maxn];
int li[maxn], ri[maxn];//记录输入海报的左右位置
int X[maxn * 3], cx;//记录输入的所有位置以及对应位置个数
int col[maxn << 4];//用颜色标记海报,-1表示该区间有多种海报(颜色)
int ans;

int n;

int b_search(int key, int n, int X[]) {//二分查找
    int l = 0, r = n - 1;
    while(l <= r) {
        int m = (l + r) >> 1;
        if(X[m] == key) return m;
        if(X[m] < key) l = m + 1;
        else r = m - 1;
    }
    return -1;
}

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

void update(int rt, int l, int r, int c, int L, int R) {//插入
    if(L <= l && r <= R) {
        col[rt] = c;
        return;
    }
    pushdown(rt);
    int mid = (l + r) >> 1;
    if(L <= mid) update(rt << 1, l, mid, c, L, R);
    if(R >= mid + 1) update(rt << 1 | 1, mid + 1, r, c, L, R);
}

void query(int rt, int l, int r) {//查询,带hash判重
    if(col[rt] != -1) {
        if(!Hash[col[rt]]) {
            ans ++;
            Hash[col[rt]] = true;
        }
        return;
    }
    if(l == r) return;
    int mid = (l + r) >> 1;
    query(rt << 1, l, mid);
    query(rt << 1 | 1, mid + 1, r);
}

int main() {
    int T;
    scanf("%d", &T);
    while(T --) {
        scanf("%d", &n);
        cx = 0; 
        for(int i = 0; i < n; i ++) {
            scanf("%d %d", &li[i], &ri[i]);
            X[cx ++] = li[i];
            X[cx ++] = ri[i];
        }
        sort(X, X + cx);
        int m = 1;
        for(int i = 1; i < cx; i ++) {//去重
            if(X[i] != X[i - 1]) X[m ++] = X[i];
        }
        for(int i = m - 1; i > 0; i --) {//解决相邻数字大于1的问题,通过插入一个数字
            if(X[i] != X[i - 1] + 1) X[m ++] = X[i - 1] + 1;
        }
        sort(X, X + m);
        memset(col, -1, sizeof(col));
        for(int i = 0; i < n; i ++) {
            int l = b_search(li[i], m, X);//二分查找离散化之后对应的那个值
            int r = b_search(ri[i], m, X);
            update(1, 0, m, i, l, r);
        }
        ans = 0;
        memset(Hash, 0, sizeof(Hash));
        query(1, 0, m);
        printf("%d\n", ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值