poj2528 Mayor's posters 线段树+离散化(经典)

来源:互联网 发布:安徽省癌症数据 编辑:程序博客网 时间:2024/06/06 00:08

题意:

市长竞选,每个市长都往墙上贴海报,海报之间彼此可以覆盖,给出粘贴顺序和每个海报的起点和长度,问最后有多少海报是可见的。

代码:

不是线段树新手应该能看懂,或者说做这题还是wa的同学,下面注释写的都是细节;

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#define MAXN 10008using namespace std;struct Node{    int l, r, v;} lines[16*MAXN];struct item {    int coord, id;} poster[4*MAXN];int n, T, li[MAXN], ri[MAXN], rini[MAXN*2];int res[MAXN];void build(int k, int l, int r) {//建树    lines[k].l = l;    lines[k].r = r;    lines[k].v = 0;    if (l == r) return ;    int mid = (l+r)/2;    build(k*2, l, mid);    build(k*2+1, mid+1, r);    return ;}void query(int k, int l, int r, int i) {//节点更新    if (lines[k].l == l && lines[k].r == r) {        lines[k].v = i;        return ;    }    //若节点k已经被覆盖, 需先将k的子节点改成k的颜色,然后本身赋0;    if (lines[k].v > 0) {        lines[k*2].v = lines[k].v;        lines[k*2+1].v = lines[k].v;        lines[k].v = 0;    }    int mid = (lines[k].l+lines[k].r)/2;    if (l > mid)        query(k*2+1, l, r, i);    else if (r <= mid)        query(k*2, l, r, i);    else {        query(k*2, l, mid, i);        query(k*2+1, mid+1, r, i);    }}int dblup(int l, int r, int v) { //二分查找ID    while (l <= r) {        int mid = (l+r)/2;        if (poster[mid].coord == v)            return poster[mid].id;        if (poster[mid].coord > v)            r = mid-1;        else l = mid+1;    }    return 0;}int cmp(item aa, item bb) {    return aa.coord < bb.coord;}void getres(int k, int res[]) {    if (lines[k].v > 0) {        res[lines[k].v] = 1;        return ;    }    if (lines[k].l == lines.r) return ;//并不是1~j-1都被覆盖了,少了会re;    getres(2*k, res);    getres(2*k+1, res);}int main() {    //freopen("in.txt", "r", stdin);    scanf("%d", &T);    while (T--) {        memset(res, 0, sizeof(res));        scanf("%d", &n);        int j = 1;        for(int i = 1; i <= n; i++) {            scanf("%d%d", li+i, ri+i);            rini[j++] = li[i];//把每一幅海报都记录下来,以便离散化;            rini[j++] = ri[i];        }        rini[j] = -1;        sort(rini+1, rini+j);        j = 1;        for(int i = 1; i <= 2*n; i++,j++) {            if (rini[i] - rini[i-1] > 1 && i != 1) {//距离大于一的,要加一个节点(不好解释);                poster[j].coord = rini[i]-1;                poster[j].id = j;                j++;            }            poster[j].coord = rini[i];            poster[j].id = j;            while (rini[i+1] == rini[i]) i++;//删除重复节点        }        build(1, 1, j-1);        for(int i = 1; i <= n; i++) {            int aa = dblup(1, j-1, li[i]);            int bb = dblup(1, j-1, ri[i]);            query(1, aa, bb, i);        }        getres(1, res);        int result = 0;        for(int i = 1; i <= n; i++)            if (res[i]) {                result++;            }        printf("%d\n", result);    }    return 0;}

贴一个精简版, 就是把结构体改成了数组,减少了很多内存,时间复杂度并没有变;

代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#define MAXN 10008using namespace std;#define lson k<<1, l, mid#define rson k<<1|1, mid+1, rstruct item {    int coord, id;} poster[4*MAXN];int n, T, li[MAXN], ri[MAXN], rini[MAXN*2], res[MAXN], lines[16*MAXN];void query(int li, int ri, int i, int k, int l, int r) {    if ( li <= l && ri >= r) {        lines[k] = i;        return ;    }    if (lines[k] > 0) {        lines[k*2] = lines[k*2+1] = lines[k];        lines[k] = 0;    }    int mid = (l+r)/2;    if (li <= mid) query(li, ri, i, lson);    if (ri > mid) query(li, ri, i, rson);}int dblup(int l, int r, int v) {    while (l <= r) {        int mid = (l+r)/2;        if (poster[mid].coord == v)            return poster[mid].id;        if (poster[mid].coord > v)            r = mid-1;        else l = mid+1;    }    return 0;}int cmp(item aa, item bb) {    return aa.coord < bb.coord;}void getres(int k, int l, int r, int res[]) {    if (lines[k] > 0) {        res[lines[k]] = 1;        return ;    }    if (l == r) return ;    int mid = (l+r)/2;    getres(lson, res);    getres(rson, res);}int main() {    //freopen("in.txt", "r", stdin);    scanf("%d", &T);    while (T--) {        memset(res, 0, sizeof(res));        memset(lines, 0, sizeof(lines));        scanf("%d", &n);        int j = 1;        for(int i = 1; i <= n; i++) {            scanf("%d%d", li+i, ri+i);            rini[j++] = li[i];            rini[j++] = ri[i];        }        rini[j] = -1;        sort(rini+1, rini+j);        j = 1;        for(int i = 1; i <= 2*n; i++,j++) {            if (rini[i] - rini[i-1] > 1 && i != 1) {                poster[j].coord = rini[i]-1;                poster[j].id = j;                j++;            }            poster[j].coord = rini[i];            poster[j].id = j;            while (rini[i+1] == rini[i]) i++;        }        for(int i = 1; i <= n; i++) {            int aa = dblup(1, j-1, li[i]);            int bb = dblup(1, j-1, ri[i]);            query(aa, bb, i, 1, 1, j-1);        }        getres(1, 1, j-1, res);        int result = 0;        for(int i = 1; i <= n; i++)            if (res[i]) {                result++;            }        printf("%d\n", result);    }    return 0;}


0 0