Hdu1828 Picture (line segment tree + discretization + scanning line)
C-Picture
Time Limit:2000 MS
Memory Limit:10000KB
64bit IO Format:% I64d & % I64uSubmit Status
Description
A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. their sides are all vertical or horizontal. each rectangle can be partially or totally covered by the others. the length of the boundary of the union of all rectangles is called the perimeter.
Write a program to calculate the perimeter. An example with 7 rectangles is shown in Figure 1.
The cZ operator? Http://www.bkjia.com/kf/ware/vc/ "target =" _ blank "class =" keylink "> memory + CjxjZW50ZXI + pgltzybzcm9" http://www.2cto.com/uploadfile/Collfiles/20140813/20140813085801256.jpg "alt =" \ ">
The vertices of all rectangles have integer coordinates.
Input
Your program is to read from standard input. the first line contains the number of rectangles pasted on the wall. in each of the subsequent lines, one can find the integer coordinates of the lower left vertex and the upper right vertex of each rectangle. the values of those coordinates are given as ordered pairs consisting of an x-coordinate followed by a y-coordinate.
0 <= number of rectangles <5000
All coordinates are in the range [-keys, 10000] and any existing rectangle has a positive area.
Output
Your program is to write to standard output. The output must contain a single line with a non-negative integer which corresponds to the perimeter for the input rectangles.
Sample Input
7-15 0 5 10-5 8 20 2515 -4 24 140 -6 16 42 15 10 2230 10 36 2034 0 40 16
Sample Output
228
Two methods are used to calculate the sum perimeter of n rectangles.
First, traverse the horizontal vertical lines separately, and use the scanning line twice. The first time from left to right, the y coordinate is discretization. After an edge is added, the sum changes. The change amount is the length of the edge, what hasn't changed is to hide it in the original image without forming a new edge. First, sum all vertical edges and calculate the horizontal edges. The final result is the total edges length. You can also avoid finding the interior edges of the image.
#include
#include
#include
#include using namespace std;#define maxn 11000struct node{int l , r ;int sum ;}cl[maxn<<2];struct node1{int k , l , r ;int flag ;}p[maxn] , q[maxn];int lazy[maxn<<2] , x[maxn] , y[maxn] ;bool cmp(node1 a,node1 b){ return a.k < b.k ;}void push_up(int rt){ if( lazy[rt] ) cl[rt].sum = cl[rt].r - cl[rt].l ; else cl[rt].sum = cl[rt<<1].sum + cl[rt<<1|1].sum ;}void creat(int rt,int l,int r,int *a){ cl[rt].l = a[l] ; cl[rt].r = a[r] ; if( r - l > 1 ) { creat(rt<<1,l,(l+r)>>1,a); creat(rt<<1|1,(l+r)>>1,r,a); push_up(rt); } else cl[rt].sum = 0 ; return ;}void update(int rt,int l,int r,int flag){ if( cl[rt].l == l && cl[rt].r == r ) { lazy[rt] += flag ; push_up(rt); } else { if( cl[rt<<1].r > l ){ int x = min(cl[rt<<1].r,r) ; update(rt<<1,l,x,flag);} if( cl[rt<<1|1].l < r ){ int x = max(cl[rt<<1|1].l,l) ; update(rt<<1|1,x,r,flag);} push_up(rt); }}int main(){int i , j , n , m , x1 , y1 , x2 , y2 , low , ans ;while(scanf("%d", &n)!=EOF){for(i = 0 ; i < n ; i++){scanf("%d %d %d %d", &x1, &y1, &x2, &y2);p[i].k = x1 ;p[i].l = y1 ;p[i].r = y2 ;p[i].flag = 1 ;p[i+n].k = x2 ;p[i+n].l = y1 ;p[i+n].r = y2 ;p[i+n].flag = -1 ;y[i+1] = y1 ;y[i+n+1] = y2 ;q[i].k = y1 ;q[i].l = x1 ;q[i].r = x2 ;q[i].flag = 1 ;q[i+n].k = y2 ;q[i+n].l = x1 ;q[i+n].r = x2 ;q[i+n].flag = -1 ;x[i+1] = x1 ;x[i+n+1] = x2 ;}ans = 0 ;memset(lazy,0,sizeof(lazy));sort(y+1,y+(2*n+1));sort(p,p+2*n,cmp);m = unique(y+1,y+(2*n+1))- (y+1);creat(1,1,m,y);ans = low = 0 ;update(1,p[0].l,p[0].r,p[0].flag);ans += fabs(low-cl[1].sum);low = cl[1].sum ;for(i = 1 ; i < 2*n ; i++) { update(1,p[i].l,p[i].r,p[i].flag); ans += fabs(low - cl[1].sum); low = cl[1].sum ; } sort(q,q+2*n,cmp); sort(x+1,x+(2*n+1)); m = unique(x+1,x+(2*n+1))-(x+1); memset(lazy,0,sizeof(lazy)); memset(cl,0,sizeof(cl)); creat(1,1,m,x); low = 0 ; update(1,q[0].l,q[0].r,q[0].flag); ans += fabs(low-cl[1].sum); low= cl[1].sum ; for(i = 1 ; i < 2*n ; i++) { update(1,q[i].l,q[i].r,q[i].flag); ans += fabs( low - cl[1].sum ); low = cl[1].sum ; } printf("%d\n", ans);}return 0;}
Second. The first method is troublesome to use two scanning lines. You can also use only one scanning line to separate y coordinates and scan x from left to right to calculate the change value of each sum, in this way, we can obtain the sum of all vertical edges. For horizontal edges, we can use (p [I]. k-p [I-1]. k) * cl [1]. num * 2. the preceding (p [I]. k-p [I-1]. k) The x coordinate difference between two adjacent line segments, cl [1]. num indicates that there are several line segments in the online segment tree. Each line segment increases the horizontal edge of the two endpoints of the line segment. Therefore, you only need to calculate the number of covered edges at that time to obtain the horizontal value-added of that segment.
Count how many line segments are covered at a time. You can use lp and rp to record whether the two endpoints of this node have been overwritten. If the coverage value is 1, then the num in this section is 1, when the two nodes are merged, the num of the parent node is equal to the num Sum of the left and right child nodes. If the rp of the Left node and the lp of the right node are both 1, then the num value of the parent node is less than 1. Finally, the entire line segment is composed of several lines.
#include
#include
#include
#include using namespace std;#define maxn 11000struct node{ int k , l , r , flag ;} p[maxn];struct node1{ int l , r , lp , rp ; int sum , num ;} cl[maxn<<2];int lazy[maxn<<2] , s[maxn] ;bool cmp(node a,node b){ return a.k < b.k ;}void push_up(int rt){ if( lazy[rt] ) { cl[rt].lp = cl[rt].rp = 1 ; cl[rt].num = 1 ; cl[rt].sum = cl[rt].r - cl[rt].l ; } else { cl[rt].sum = cl[rt<<1].sum + cl[rt<<1|1].sum ; cl[rt].num = cl[rt<<1].num + cl[rt<<1|1].num ; cl[rt].lp = cl[rt<<1].lp ; cl[rt].rp = cl[rt<<1|1].rp ; if( cl[rt<<1].rp && cl[rt<<1|1].lp ) cl[rt].num-- ; }}void creat(int rt,int l,int r){ cl[rt].l = s[l] ; cl[rt].r = s[r] ; cl[rt].lp = cl[rt].rp = 0 ; if( r - l > 1 ) { creat(rt<<1,l,(l+r)/2); creat(rt<<1|1,(l+r)/2,r); push_up(rt); } else cl[rt].num = cl[rt].sum = 0 ;}void update(int rt,int l,int r,int flag){ if( cl[rt].l == l && cl[rt].r == r ) { lazy[rt] += flag ; push_up(rt); } else { if( cl[rt<<1].r > l ){ int x = min(r,cl[rt<<1].r) ; update(rt<<1,l,x,flag);} if( cl[rt<<1|1].l < r ){ int x = max(l,cl[rt<<1|1].l) ; update(rt<<1|1,x,r,flag);} push_up(rt); } return ;}int main(){ int n , m , i , j , x1 , y1 , x2 , y2 , ans , low ; while(scanf("%d", &n)!=EOF) { for(i = 0 ; i < n ; i++) { scanf("%d %d %d %d", &x1, &y1, &x2, &y2); p[i].k = x1 ; p[i].l = y1 ; p[i].r = y2 ;p[i].flag = 1 ; p[i+n].k = x2 ;p[i+n].l = y1 ; p[i+n].r = y2 ; p[i+n].flag = -1 ; s[i+1] = y1 ; s[i+n+1] = y2 ; } sort(s+1,s+(2*n+1)); sort(p,p+2*n,cmp); m = unique(s+1,s+(2*n+1))-(s+1) ; memset(lazy,0,sizeof(lazy)); creat(1,1,m); ans = 0 ; low = 0 ; update(1,p[0].l,p[0].r,p[0].flag); ans += fabs( low - cl[1].sum ); low = cl[1].sum ; for(i = 1 ; i < 2*n ; i++) { ans += ( p[i].k - p[i-1].k )*cl[1].num*2 ; update(1,p[i].l,p[i].r,p[i].flag); ans += fabs( low - cl[1].sum ); low = cl[1].sum ; } printf("%d\n", ans); } return 0;}