poj 2528(区间修改+离散化)

来源:互联网 发布:模拟器软件闪退 编辑:程序博客网 时间:2024/06/05 01:17

题意:有一个黑板上贴海报,给出每个海报在黑板上的覆盖区间为l r,问最后多少个海报是可见的。
题解:因为l r取值到1e7,肯定是要离散化的,但普通的离散化会出问题,比如[1,10],[1,4],[6,10]普通得到答案是2,但其实是3,改进的离散化方法如果两个数字相差大于1,就在中间补一个数字。

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;const int N = 10005;int n, l[N], r[N], a[N << 3], tree[N << 4], vis[N], res;void pushdown(int k) {    if (tree[k] != -1) {        tree[k * 2] = tree[k * 2 + 1] = tree[k];        tree[k] = -1;    }}void modify(int k, int left, int right, int l1, int r1, int x) {     if (l1 <= left && right <= r1) {         tree[k] = x;         return;     }     pushdown(k);     int mid = (left + right) / 2;     if (mid >= l1)        modify(k * 2, left, mid, l1, r1, x);    if (mid < r1)        modify(k * 2 + 1, mid + 1, right, l1, r1, x);}void query(int k, int left, int right) {    if (left == right) {        if (!vis[tree[k]]) {            res++;            vis[tree[k]] = 1;       }       return;    }    pushdown(k);    int mid = (left + right) / 2;    query(k * 2, left, mid);    query(k * 2 + 1, mid + 1, right);}int main() {    int t;    scanf ("%d", &t);    while (t--) {        memset(tree, -1, sizeof(tree));        memset(vis, 0, sizeof(vis));        int cnt = 0;        scanf("%d", &n);        for (int i = 1; i <= n; i++) {             scanf ("%d%d", &l[i], &r[i]);             a[++cnt] = l[i];             a[++cnt] = r[i];        }        sort(a + 1, a + 1 + cnt);        cnt = unique(a + 1, a + 1 + cnt) - (a + 1);        int cnt2 = cnt;        for (int i = 2; i <= cnt; i++)            if (a[i] - a[i - 1] > 1)                a[++cnt2] = a[i] - 1;        cnt = cnt2;        sort(a + 1, a + 1 + cnt);        for (int i = 1; i <= n; i++) {            int l1 = lower_bound(a + 1, a + 1 + cnt, l[i]) - a;            int r1 = lower_bound(a + 1, a + 1 + cnt, r[i]) - a;            modify(1, 1, cnt, l1, r1, i);        }    res = 0;    query(1, 1, cnt);        printf("%d\n", res);    }    return 0;}
0 0
原创粉丝点击