多个矩形边缘周长

来源:互联网 发布:315曝光的淘宝代购店铺 编辑:程序博客网 时间:2024/05/17 00:13

世事还是如此无常,关键是要有平常心!

http://www.cnblogs.com/Booble/archive/2010/10/10/1847163.html

详细耐心的解说,包您一看就懂,假一罚十!


以下是poj1177求多个矩形边缘周长的代码以及注释:

         吐槽:WA了很久很久,原因是因为什么呢?    maxn定义得太小了

         人家的坐标是 [-10000,10000],即使离散化,应该也有很多个点。

 

对于我容易错的地方:

R > m 要递归右子树

maxn

离散化的时候 开始的指针为1

//attention: //将线段树看成一个线段,它的每个点的意义是包括它本身的单位向后为一的线段#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#define lson l,m, rt << 1#define rson m + 1, r, rt << 1 | 1#define maxn 22222using namespace std;//分别表示该区间的左端点、右端点表示的线段的右端点是否被覆盖bool lbd[maxn << 2],rbd[maxn << 2];int len[maxn << 2];//表示该节点区间所覆盖的长度int cnt[maxn << 2],numseg[maxn << 2];//分别表示该区间有几条线段覆盖、从远处看有几条线段struct Seg{int l , r , h , s;Seg() {}Seg(int a,int b,int c,int d):l(a) , r(b) , h(c) , s(d) {}bool operator < (const Seg &cmp) const {if (h == cmp.h) return s > cmp.s;return h < cmp.h;}}seg[maxn << 1];void push_up(int rt, int l, int r){    if(cnt[rt]){        lbd[rt] = rbd[rt] = true;        len[rt] = r - l + 1;        numseg[rt] = 2;    }else if(l == r){        len[rt] = numseg[rt] = lbd[rt] = rbd[rt] =  0;    }else{        lbd[rt] = lbd[rt << 1];      rbd[rt] = rbd[rt << 1 | 1];        len[rt] = len[rt << 1] + len[rt << 1 | 1];        numseg[rt] = numseg[rt << 1] + numseg[rt << 1 | 1];        if(lbd[rt << 1 | 1] && rbd[rt << 1])    numseg[rt] -= 2;    }}void update(int L, int R, int c, int l ,int r, int rt){    if(L <= l && r <= R){        cnt[rt] += c;        push_up(rt,l,r);    return ;    }    int m = (l + r) >> 1;    if(L <= m) update(L,R,c,lson);    if(R > m) update(L,R,c,rson);    push_up(rt,l,r);}int main(){    int n,a,b,c,d,s;    int ret;    while(scanf("%d",&n)!= EOF){        s = 0;  ret = 0;        int lt = 1000000, rt = - 100000;        memset(len,0,sizeof(len));        memset(numseg,0,sizeof(numseg));        memset(cnt,0,sizeof(cnt));        memset(lbd,0,sizeof(lbd));        memset(rbd,0,sizeof(rbd));        for(int i = 0; i < n; i ++){            scanf("%d%d%d%d",&a,&b,&c,&d);            lt = min(lt,a);            rt = max(rt,c);        //1表示矩形的下边            seg[s ++] = Seg(a,c,b,1);        //-1表示矩形的上边。        //我是从下往上扫描,所以遇到下边即插入,遇到上边即删除        //由update里面的cnt[rt] += c 反应            seg[s ++] = Seg(a,c,d,-1);        }        sort(seg,seg+ s);   //排序保证从下往上扫描        int last = 0;   seg[s] .h = 0;        for(int i = 0; i < s ; i ++){            if(seg[i].l <seg[i].r)            //正因为线段树的定义,这里才插入的是 r - 1                update(seg[i].l,seg[i].r - 1,seg[i].s,lt,rt,1);            ret += abs(len[1] - last);  //差值            ret += numseg[1] * (seg[i + 1].h - seg[i].h);   //线段数 * 统计区间长度            last = len[1];        }        printf("%d\n",ret);    }    return 0;}int bin(int low, int high, double key,double X[]){    while(low < high){        int mid = (low + high) >> 1;        if(X[mid] < key)    low = mid + 1;        else high = mid;    }    return low;}