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