先贴个代码,题解明天补上,先去补读书笔记。。。
熬夜通宵补完了坑爹的读书笔记和社会实践报告,七千字额,呕心沥血的大作
题意:一个二维的平面内许多边平行于坐标轴的矩形相交,组成了比较复杂的多边行,求多边形的周长。
思路:一开始感觉数据范围这么大,肯定要用线段树优化的,结果作了半天的线段书,也没想出该怎么维护。。。。。。感觉弱爆了。。。。。。然后试了试不用线段树,结果31MS水过了。。
下面说一下自己对扫描线的理解:
扫描线给人的感觉就是在目标区域内有一条线按照一定的要求从一端扫到另一端,在扫描的过程内会碰到事先标记好的事件点,从而计算目标值。
对于这道题来说,目标值就是多边形的周长,事件点即为矩形的边。
以与Y轴平行的边为例。
扫描线的每条线段初始值为零,每次碰到左边则加一,碰到右边则减一,当标记从0变为1或从1变为0时,加上这一小段的值,当然还要注意去重边,如下面这组数据。
2
0 0 2 2
2 1 3 3
显然与X轴平行的边也一样计算。
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <algorithm>
#define LL long long
#define Max(a,b) (a) > (b) ? (a) : (b)
#define Min(a,b) (a) < (b) ? (a) : (b)
#define EPS (1e-8)
#define Left (1)
#define Right (-1)
using namespace std;
struct P
{
int x,y;
};
struct L
{
P p1,p2;
int mark;
}lx[10100],ly[10100];
struct S
{
int cover,site;
}seg[10100];
int px[10010],py[10010];
int delsame(int *p,int n)
{
if(n == 0)
return 0;
int top,i;
for(i = 1,top = 1;i < n; ++i)
{
if(p[i] != p[i-1])
p[top++] = p[i];
}
return top;
}
bool cmp(int a,int b)
{
return a < b;
}
bool cmp_x(L l1,L l2)
{
return l1.p1.x < l2.p1.x;
}
bool cmp_y(L l1,L l2)
{
return l1.p1.y < l2.p1.y;
}
int BS(int *p,int m,int n)
{
int s = 0,e = n - 1,mid;
while(s < e)
{
mid = (s+e)>>1;
if(p[mid] == m)
return mid;
if(p[mid] < m)
{
s = mid+1;
}
else
{
e = mid-1;
}
}
mid = (s+e)>>1;
if(p[mid] == m)
return mid;
return -1;
}
int main()
{
int n;
int t1,t2,ty,tx;
P p1,p2;
int i,j,s1,s2;
int Perimeter;
while(scanf("%d",&n) != EOF)
{
Perimeter = 0;
t1 = t2 = tx = ty = 0 ;
for(i = 0;i < n; ++i)
{
scanf("%d %d %d %d",&p1.x,&p1.y,&p2.x,&p2.y);
lx[t1].p1 = p1;
lx[t1].p2.x = p2.x;
lx[t1].p2.y = p1.y;
lx[t1].mark = Left;
++t1;
lx[t1].p2 = p2;
lx[t1].p1.x = p1.x;
lx[t1].p1.y = p2.y;
lx[t1].mark = Right;
++t1;
ly[t2].p1 = p1;
ly[t2].p2.x = p1.x;
ly[t2].p2.y = p2.y;
ly[t2].mark = Left;
++t2;
ly[t2].p2 = p2;
ly[t2].p1.x = p2.x;
ly[t2].p1.y = p1.y;
ly[t2].mark = Right;
++t2;
px[tx++] = p1.x;
px[tx++] = p2.x;
py[ty++] = p1.y;
py[ty++] = p2.y;
}
sort(px,px+ty,cmp);
sort(py,py+ty,cmp);
sort(lx,lx+t1,cmp_y);
sort(ly,ly+t2,cmp_x);
tx = delsame(px,tx);
ty = delsame(py,ty);
for(i = 0;i <= tx; ++i)
{
seg[i].cover = 0;
seg[i].site = -10010;
}
for(i = 0;i < t1; ++i)
{
s1 = BS(px,lx[i].p1.x,tx);
s2 = BS(px,lx[i].p2.x,tx);
for(j = s1;j < s2; ++j)
{
if(seg[j].cover == 0)
{
if(seg[j].site != lx[i].p1.y)
{
Perimeter += (px[j+1]-px[j]);
}
else
{
Perimeter -= (px[j+1]-px[j]);
}
seg[j].site = lx[i].p1.y;
seg[j].cover += lx[i].mark;
}
else
{
seg[j].cover += lx[i].mark;
if(seg[j].cover == 0)
{
Perimeter += (px[j+1]-px[j]);
seg[j].site = lx[i].p1.y;
}
}
}
}
for(i = 0;i <= ty; ++i)
{
seg[i].cover = 0;
seg[i].site = -10010;
}
for(i = 0;i < t2; ++i)
{
s1 = BS(py,ly[i].p1.y,ty);
s2 = BS(py,ly[i].p2.y,ty);
for(j = s1;j < s2; ++j)
{
if(seg[j].cover == 0)
{
if(seg[j].site != ly[i].p1.x)
{
Perimeter += (py[j+1]-py[j]);
}
else
{
Perimeter -= (py[j+1]-py[j]);
}
seg[j].site = ly[i].p1.x;
seg[j].cover += ly[i].mark;
}
else
{
seg[j].cover += ly[i].mark;
if(seg[j].cover == 0)
{
Perimeter += (py[j+1]-py[j]);
seg[j].site = ly[i].p1.x;
}
}
}
}
cout<<Perimeter<<endl;
}
return 0;
}