【hdu1828/poj1177】线段树求矩形周长并

题意如图

题解:这题非常类似与矩形面积并,也是维护一个被覆盖了一次以上的线段总长。

但是周长要算新出现的,所以每次都要和上一次做差求绝对值。

x轴做一遍,y轴做一遍。

但是有个问题:矩形边界重合的时候的处理。举个例子,在处理x轴的时候:

怎么处理呢?我们在对y排序的时候把下边界(下边界+1,上边界-1)排在上边界前面,这样做就不会重复算了。

 

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<iostream>
  6 #include<algorithm>
  7 using namespace std;
  8 
  9 typedef long long LL;
 10 const int N=10*5000,INF=(int)1e9;
 11 struct node{
 12     int x1,x2,y,d;
 13 }a[N];
 14 struct point{
 15     int x,y;LL d;
 16 }p[N];
 17 struct trnode{
 18     int l,r,lc,rc,cnt;
 19     LL rl,len;
 20 }t[2*N];
 21 int n,mx,pl,al,tl,z[N][4];
 22 LL num[N];
 23 
 24 bool cmp_d(point x,point y){return x.d<y.d;}
 25 bool cmp_y(node x,node y)
 26 {
 27     if(x.y==y.y) return x.d>y.d;//处理重边
 28     else return x.y<y.y;
 29 }
 30 void inp(int x,int y,int d){p[++pl].x=x;p[pl].y=y;p[pl].d=d;}
 31 void ina(int x1,int x2,int y,int d){a[++al].x1=x1;a[al].x2=x2;a[al].y=y;a[al].d=d;}
 32 int myabs(int x){return x>0 ? x:-x;}
 33 int maxx(int x,int y){return x>y ? x:y;}
 34 
 35 void unique()
 36 {
 37     int now=0;p[0].d=INF;
 38     sort(p+1,p+1+pl,cmp_d);
 39     for(int i=1;i<=pl;i++)
 40     {
 41         if(p[i].d!=p[i-1].d) now++,num[now]=(LL)p[i].d;
 42         z[p[i].x][p[i].y]=now;
 43     }
 44     mx=now;
 45 }
 46 
 47 void make_edge()
 48 {
 49     al=0;mx=0;
 50     for(int i=1;i<=n;i++)
 51     {
 52         if(z[i][0]>z[i][2]) swap(z[i][0],z[i][2]);
 53         if(z[i][1]>z[i][3]) swap(z[i][1],z[i][3]);
 54         ina(z[i][0],z[i][2],z[i][1],1);
 55         ina(z[i][0],z[i][2],z[i][3],-1);
 56         mx=maxx(mx,z[i][2]);
 57     }
 58     // ina(1,mx-1,INF,-1);
 59 }
 60 
 61 int bt(int l,int r)
 62 {
 63     int x=++tl;
 64     t[x].l=l;t[x].r=r;
 65     t[x].lc=t[x].rc=0;
 66     t[x].cnt=0;t[x].len=0;
 67     t[x].rl=num[r+1]-num[l];
 68     if(l<r)
 69     {
 70         int mid=(l+r)/2;
 71         t[x].lc=bt(l,mid);
 72         t[x].rc=bt(mid+1,r);
 73     }
 74     return x;
 75 }
 76 
 77 void upd(int x)
 78 {
 79     int lc=t[x].lc,rc=t[x].rc;
 80     if(t[x].cnt>=1) t[x].len=t[x].rl;
 81     else t[x].len=t[lc].len+t[rc].len;
 82 }
 83 
 84 void change(int x,int l,int r,int d)
 85 {
 86     if(t[x].l==l && t[x].r==r) 
 87     {
 88         t[x].cnt+=d;
 89         upd(x);
 90         return;
 91     }
 92     int lc=t[x].lc,rc=t[x].rc,mid=(t[x].l+t[x].r)/2;
 93     if(r<=mid) change(lc,l,r,d);
 94     else if(l>mid) change(rc,l,r,d);
 95     else
 96     {
 97         change(lc,l,mid,d);
 98         change(rc,mid+1,r,d);
 99     }
100     upd(x);
101 }
102 
103 void output()
104 {
105     for(int i=1;i<=tl;i++)
106         printf("l = %d  r = %d  cnt = %d  len  = %lf  rl = %lf \n",t[i].l,t[i].r,t[i].cnt,t[i].len,t[i].rl);
107 }
108 
109 int main()
110 {
111     freopen("a.in","r",stdin);
112     while(scanf("%d",&n)!=EOF)
113     {
114         LL pre,ans,now;ans=0;pl=0;
115         for(int i=1;i<=n;i++)
116         {
117             for(int j=0;j<=3;j++)
118             {
119                 scanf("%d",&z[i][j]);
120                 inp(i,j,z[i][j]);
121             }
122         }
123         unique();
124         for(int k=0;k<=1;k++)
125         {
126             if(k==1)
127             {
128                 for(int i=1;i<=n;i++) swap(z[i][0],z[i][1]),swap(z[i][2],z[i][3]);    
129             }
130             make_edge();
131             sort(a+1,a+1+al,cmp_y);
132             tl=0;bt(1,mx-1);
133             pre=0;
134             for(int i=1;i<=al;i++)
135             {
136                 change(1,a[i].x1,a[i].x2-1,a[i].d);
137                 now=t[1].len;
138                 ans+=myabs(now-pre);
139                 pre=now;
140             }
141             // printf("ans = %d\n",ans);
142         }
143         printf("%lld\n",ans);    
144     }
145     return 0;
146 }

 

posted @ 2016-11-03 10:11  拦路雨偏似雪花  阅读(453)  评论(0编辑  收藏  举报