【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 }

    

原文地址:https://www.cnblogs.com/kane0526/p/2935340.html