硬上了面積並,覺得有點爽。。
掃描線+線段樹嘛。。
重點:掃描線法:假想有一條掃描線,從左往右(從右往左),或者從下往上(從上往下)掃描過整個多邊形(或者說畸形。。多個矩形疊加後的那個圖形)
掃描之前還需要做一個工作,就是保存好所有矩形的上下邊,並且按照它們所處的高度進行排序,另外如果是上邊我們給他一個值-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.