题意很简单,就是求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 }