矩形的面積並

硬上了面積並,覺得有點爽。。

掃描線+線段樹嘛。。

重點:掃描線法:假想有一條掃描線,從左往右(從右往左),或者從下往上(從上往下)掃描過整個多邊形(或者說畸形。。多個矩形疊加後的那個圖形)

   掃描之前還需要做一個工作,就是保存好所有矩形的上下邊,並且按照它們所處的高度進行排序,另外如果是上邊我們給他一個值-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.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章