硬上了面积并,觉得有点爽。。
扫描线+线段树嘛。。
重点:扫描线法:假想有一条扫描线,从左往右(从右往左),或者从下往上(从上往下)扫描过整个多边形(或者说畸形。。多个矩形叠加后的那个图形)
扫描之前还需要做一个工作,就是保存好所有矩形的上下边,并且按照它们所处的高度进行排序,另外如果是上边我们给他一个值-1,下边给他一个值1,我们用一个结构体来保存所有的上下边
struct segment
{
double l,r,h; //l,r表示这条上下边的左右坐标,h是这条边所处的高度
int f; //所赋的值,1或-1
}
接着扫描线从下往上扫描,每遇到一条上下边就停下来,将这条线段投影到总区间上(总区间就是整个多边形横跨的长度),这个投影对应的其实是个插入和删除线段操作。还记得给他们赋的值1或-1吗,下边是1,扫描到下边的话相当于往总区间插入一条线段,上边-1,扫描到上边相当于在总区间删除一条线段(如果说插入删除比较抽象,那么就直白说,扫描到下边,投影到总区间,对应的那一段的值都要增1,扫描到上边对应的那一段的值都要减1,如果总区间某一段的值为0,说明其实没有线段覆盖到它,为正数则有,那会不会为负数呢?是不可能的,可以自己思考一下)。
每扫描到一条上下边后并投影到总区间后,就判断总区间现在被覆盖的总长度,然后用下一条边的高度减去当前这条边的高度,乘上总区间被覆盖的长度,就能得到一块面积,并依此做下去,就能得到最后的面积
(这个过程其实一点都不难,只是看文字较难体会,建议纸上画图,一画即可明白,下面献上一图希望有帮助)
我就是看这个看懂的。。
所以它是怎么实现的我就不说了。。
那么我要说的是线段树
或许要问:有没有必要打lazy-tag呢?。。
其实没有必要。。
看我的代码,就会明白没有lazy-tag也是可以的。。
因为我们要求的只是最上层的,下面的没有用。。
也许下层的sum是错误的,但只要sum[1]正确即可。。
Code:
const shuru='matrix.in';
shuchu='matrix.out';
maxm=8500000;
maxn=200000;
type treenode=record
left,right:longint;
sum,cover:int64;
end;
var tree:Array[0..maxm+1] of treenode;
y,x1,x2,k:array[0..maxn] of int64;
t,num,a,b,c,d,maxlen,i,j,n:longint;
ans:int64;
procedure build(x,l,r:longint);inline;
var mid:longint;
begin
tree[x].left:=l; tree[x].right:=r;
mid:=(l+r) shr 1;
if mid<>l then begin
build(x shl 1,l,mid);
build(x shl 1+1,mid,r);
end;
end;
procedure qsort(left,right:longint);inline;
var i,j,mid:longint;
begin
i:=left; j:=right; mid:=y[(i+j) div 2];
repeat
while y[i]<mid do inc(i);
while y[j]>mid do dec(j);
if i<=j then begin
t:=y[i]; y[i]:=y[j]; y[j]:=t;
t:=x1[i]; x1[i]:=x1[j]; x1[j]:=t;
t:=x2[i]; x2[i]:=x2[j]; x2[j]:=t;
t:=k[i]; k[i]:=k[j]; k[j]:=t;
inc(i); dec(j);
end;
until i>j;
if j>left then qsort(left,j);
if i<right then qsort(i,right);
end;
function max(a,b:longint):longint;inline;
begin
if a>b then exit(a);
exit(b);
end;
procedure init;
begin
readln(n);
for i:=1 to n do
begin
readln(a,b,c,d);
inc(num);
y[num]:=b;
x1[num]:=a;
x2[num]:=a+c;
k[num]:=1;
inc(num);
y[num]:=b+d;
x1[num]:=a;
x2[num]:=a+c;
k[num]:=-1;
maxlen:=max(maxlen,a+c);
end;
end;
procedure ins(x,a,b,data:longint);inline;
var mid:longint;
begin
if (a<=tree[x].left) and (b>=tree[x].right) then
inc(tree[x].cover,data)
else
begin
mid:=(tree[x].left+tree[x].right) shr 1;
if a<mid then ins(x shl 1,a,b,data);
if b>mid then ins(x shl 1+1,a,b,data);
end;
if tree[x].cover>0 then tree[x].sum:=tree[x].right-tree[x].left
else tree[x].sum:=tree[x shl 1].sum+tree[x shl 1+1].sum;
end;
procedure main;
begin
init;
qsort(1,2*n);
build(1,0,maxlen);
ins(1,x1[1],x2[1],k[1]);
for i:=2 to 2*n do
begin
ans:=ans+(y[i]-y[i-1])*tree[1].sum;
ins(1,x1[i],x2[i],k[i]);
end;
writeln(ans);
end;
begin
main;
end.