HDU 1828 / POJ 1177 Picture --线段树求矩形周长并

题意:给n个矩形,求矩形周长并

解法:跟求矩形面积并差不多,不过线段树节点记录的为:

len: 此区间线段长度

cover: 此区间是否被整个覆盖

lmark,rmark: 此区间左右端点是否被覆盖

num: 此区间分离开的线段的条数

重点在转移的地方,不难理解。

代码:

#include <iostream>

#include <cmath>

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <cmath>

#include <algorithm>

using namespace std;

#define N 10007



struct node

{

    int cov,len,num,lmark,rmark;

}tree[8*N];



struct Line

{

    int y1,y2,x;

    int cov;

}line[2*N];

int yy[2*N];



int cmp(Line ka,Line kb)

{

    return ka.x < kb.x;

}



int bsearch(int l,int r,int x)

{

    while(l <= r)

    {

        int mid = (l+r)/2;

        if(x == yy[mid])

            return mid;

        if(x > yy[mid])

            l = mid+1;

        else

            r = mid-1;

    }

    return l;

}



void build(int l,int r,int rt)

{

    tree[rt].cov = tree[rt].len = tree[rt].num = tree[rt].lmark = tree[rt].rmark = 0;

    if(l == r-1) return;

    int mid = (l+r)/2;

    build(l,mid,2*rt);

    build(mid,r,2*rt+1);

}



void pushup(int l,int r,int rt)

{

    if(tree[rt].cov)

    {

        tree[rt].len = yy[r]-yy[l];

        tree[rt].lmark = tree[rt].rmark = 1;

        tree[rt].num = 1;

    }

    else if(l+1 == r)

        tree[rt].len = tree[rt].num = tree[rt].lmark = tree[rt].rmark = 0;

    else

    {

        tree[rt].len = tree[2*rt].len + tree[2*rt+1].len;

        tree[rt].lmark = tree[2*rt].lmark;

        tree[rt].rmark = tree[2*rt+1].rmark;

        tree[rt].num = tree[2*rt].num+tree[2*rt+1].num-tree[2*rt].rmark*tree[2*rt+1].lmark;

        //如果左右区间连续,那么可以合并,减少一个区间

    }

}



void update(int l,int r,int aa,int bb,int cover,int rt)

{

    if(aa <= l && bb >= r)

    {

        tree[rt].cov += cover;

        pushup(l,r,rt);

        return;

    }

    if(l+1 == r) return;

    int mid = (l+r)/2;

    if(aa <= mid)

        update(l,mid,aa,bb,cover,2*rt);

    if(bb > mid)

        update(mid,r,aa,bb,cover,2*rt+1);

    pushup(l,r,rt);

}



int main()

{

    int n,m,cs = 1,i,j;

    int x1,y1,x2,y2;

    while(scanf("%d",&n)!=EOF)

    {

        m = 1;

        for(i=0;i<n;i++)

        {

            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);

            line[m].x = x1,line[m].y1 = y1,line[m].y2 = y2,line[m].cov = 1,yy[m++] = y1;

            line[m].x = x2,line[m].y1 = y1,line[m].y2 = y2,line[m].cov = -1,yy[m++] = y2;

        }

        m--;

        sort(yy+1,yy+m+1);

        int cnt = 2;

        for(i=2;i<=m;i++)

        {

            if(yy[i] != yy[i-1])

                yy[cnt++] = yy[i];

        }

        cnt--;

        build(1,cnt,1);

        sort(line+1,line+m+1,cmp);

        int ans = 0;

        int last = 0;

        for(i=1;i<=m;i++)

        {

            int L = bsearch(1,cnt,line[i].y1);

            int R = bsearch(1,cnt,line[i].y2);

            update(1,cnt,L,R,line[i].cov,1);

            ans += abs(last - tree[1].len);

            if(i == m) break;

            ans += tree[1].num*2*(line[i+1].x-line[i].x);

            last = tree[1].len;

        }

        printf("%d\n",ans);

    }

    return 0;

}
View Code

 

你可能感兴趣的:(poj)