【hdu 1828 Picture】 线段树之扫面线(周长并)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1828

题目大意: 给你多个矩形,求他们合并和的周长,被覆盖的边不能算进周长之内。

 

解题思路:

     其实周长并和面积并没什么很大的区别,只不过周长并增加了判断左右端点是否被覆盖的标记 lbd 和rbd 数组, 以及numseg 数组 记录连续区间段数。

     numseg : 一根扫描线扫描过去,会记录有多少个连续的区间段,每个连续的区间段都有两条相等的竖边,而每次扫描过去竖边长度都相等。

     参考文献 :陈宏《数据结构的选择与算法效率》

 

View Code
  1 #include <iostream>

  2 #include <cstdio>

  3 #include <cstring>

  4 #include <algorithm>

  5 using namespace std;

  6 

  7 #define lz 2*u,l,mid

  8 #define rz 2*u+1,mid+1,r

  9 const int maxn=22222;

 10 int sum[4*maxn];              ///记录被覆盖区间的长度

 11 int lbd[4*maxn], rbd[4*maxn]; ///记录左右端点是否被覆盖

 12 int numseg[4*maxn];            ///记录该区间连续的段数

 13 int flag[4*maxn];              /// 记录该区间是否被覆盖

 14 

 15 struct Node

 16 {

 17     int lx, rx, y, s;

 18     int lbd, rbd;

 19     Node() {};

 20     Node(int lx_, int rx_, int y_, int s_)

 21     {

 22         lx=lx_, rx=rx_, y=y_, s=s_;

 23     }

 24     bool operator <(const Node &S) const

 25     {

 26         if(y==S.y) return s>S.s;

 27         return y<S.y;

 28     }

 29 } line[maxn];

 30 

 31 void push_up(int u, int l, int r)

 32 {

 33     if(flag[u])

 34     {

 35         lbd[u]=1;

 36         rbd[u]=1;

 37         sum[u]=r-l+1;

 38         numseg[u]=2;

 39     }

 40     else if(l==r)

 41     {

 42         sum[u]=numseg[u]=lbd[u]=rbd[u]=0;

 43     }

 44     else

 45     {

 46         lbd[u]=lbd[2*u];

 47         rbd[u]=rbd[2*u+1];

 48         sum[u]=sum[2*u]+sum[2*u+1];

 49         numseg[u]=numseg[2*u]+numseg[2*u+1];

 50         if(rbd[2*u]&&lbd[2*u+1]) numseg[u]-=2;

 51     }

 52 }

 53 

 54 void Update(int u, int l, int r, int tl, int tr, int c)

 55 {

 56     if(tl<=l&&r<=tr)

 57     {

 58         flag[u]+=c;

 59         push_up(u,l,r);

 60         return ;

 61     }

 62     int mid=(l+r)>>1;

 63     if(tr<=mid) Update(lz,tl,tr,c);

 64     else if(tl>mid) Update(rz,tl,tr,c);

 65     else

 66     {

 67         Update(lz,tl,mid,c);

 68         Update(rz,mid+1,tr,c);

 69     }

 70     push_up(u,l,r);

 71 }

 72 

 73 int main()

 74 {

 75     int n;

 76     while(cin >> n)

 77     {

 78         int x1, x2, y1, y2;

 79         int num=0, lbd=10000, rbd=-10000;

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

 81         {

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

 83             line[++num]=Node(x1,x2,y1,1);

 84             line[++num]=Node(x1,x2,y2,-1);

 85             lbd=min(lbd,x1);

 86             rbd=max(rbd,x2);

 87         }

 88         sort(line+1,line+num+1);

 89         int ans=0, last=0;

 90         for(int i=1; i<=num; i++)

 91         {

 92             Update(1,lbd,rbd-1,line[i].lx,line[i].rx-1,line[i].s);

 93             ans+=numseg[1]*(line[i+1].y-line[i].y);

 94             ans+=abs(sum[1]-last);

 95             last=sum[1];

 96         }

 97         cout << ans <<endl;

 98     }

 99     return 0;

100 }

 

    

你可能感兴趣的:(HDU)