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