题意很简单,就是求n个矩形的周长并。方法跟求面积并差不多,只是在扫描矩形上下边时需要统计竖直边的个数,
先排个序,每次更新求出变化的和。
View Code
1 #include <stdio.h> 2 #include <math.h> 3 #define lson l,m,rt<<1 4 #define rson m+1,r,rt<<1|1 5 #define maxn 20005 6 struct node 7 { 8 int len,lnum,rnum,cnt,segnum; 9 }setree[maxn<<2]; 10 struct 11 { 12 int l,r,h,side; 13 }xx[maxn]; 14 int max(int a,int b) 15 { 16 return a>b?a:b; 17 } 18 int min(int a,int b) 19 { 20 return a<b?a:b; 21 } 22 void build(int l,int r,int rt) 23 { 24 setree[rt].len=0; 25 setree[rt].cnt=0; 26 setree[rt].segnum=0; 27 setree[rt].lnum=setree[rt].rnum=0; 28 if(l==r) 29 return; 30 int m=(l+r)>>1; 31 build(lson); 32 build(rson); 33 } 34 void pushup(int rt,int len) 35 { 36 if(setree[rt].cnt){ 37 setree[rt].len=len; 38 setree[rt].lnum=setree[rt].rnum=1; 39 setree[rt].segnum=2; 40 } 41 else if(len==1){ 42 setree[rt].lnum=setree[rt].rnum=setree[rt].segnum=setree[rt].len=0; 43 } 44 else{ 45 setree[rt].len=setree[rt<<1].len+setree[rt<<1|1].len; 46 setree[rt].segnum=setree[rt<<1].segnum+setree[rt<<1|1].segnum; 47 setree[rt].lnum=setree[rt<<1].lnum; 48 setree[rt].rnum=setree[rt<<1|1].rnum; 49 if(setree[rt<<1].rnum&&setree[rt<<1|1].lnum) 50 setree[rt].segnum-=2; 51 } 52 } 53 void update(int l,int r,int rt,int L,int R,int cnt) 54 { 55 if(L<=l&&r<=R){ 56 setree[rt].cnt+=cnt; 57 pushup(rt,r-l+1); 58 return; 59 } 60 int m=(l+r)>>1; 61 if(L<=m) 62 update(lson,L,R,cnt); 63 if(R>m) 64 update(rson,L,R,cnt); 65 pushup(rt,r-l+1); 66 } 67 void quicksort(int l,int r) 68 { 69 if(l>=r) 70 return; 71 int i=l,j=r,tl=xx[l].l,tr=xx[l].r,ts=xx[l].side,th=xx[l].h; 72 while(i<j){ 73 while(xx[j].h>=th&&i<j) 74 j--; 75 if(i<j){ 76 xx[i].l=xx[j].l; 77 xx[i].r=xx[j].r; 78 xx[i].h=xx[j].h; 79 xx[i].side=xx[j].side; 80 i++; 81 } 82 while(xx[i].h<th&&i<j) 83 i++; 84 if(i<j){ 85 xx[j].l=xx[i].l; 86 xx[j].r=xx[i].r; 87 xx[j].h=xx[i].h; 88 xx[j].side=xx[i].side; 89 j--; 90 } 91 } 92 xx[i].l=tl; 93 xx[i].r=tr; 94 xx[i].h=th; 95 xx[i].side=ts; 96 quicksort(l,i-1); 97 quicksort(i+1,r); 98 } 99 int main() 100 { 101 int n; 102 while(~scanf("%d",&n)){ 103 int lbd=10000,rbd=-10000; 104 int m=0; 105 for(int i=0;i<n;i++){ 106 int a,b,c,d; 107 scanf("%d%d%d%d",&a,&b,&c,&d); 108 lbd=min(lbd,a); 109 rbd=max(rbd,c); 110 xx[m].l=xx[m+1].l=a; 111 xx[m].r=xx[m+1].r=c; 112 xx[m].h=b; 113 xx[m+1].h=d; 114 xx[m].side=1; 115 xx[m+1].side=-1; 116 m+=2; 117 } 118 quicksort(0,m-1); 119 build(lbd,rbd,1); 120 int ret=0,last=0; 121 for(int i=0;i<m;i++){ 122 update(lbd,rbd,1,xx[i].l,xx[i].r-1,xx[i].side); 123 ret+=setree[1].segnum*(xx[i+1].h-xx[i].h); 124 ret+=abs(setree[1].len-last); 125 last=setree[1].len; 126 } 127 printf("%d\n",ret); 128 } 129 }