火星探險 Mars

2021-08-17 15:56:32 字數 3385 閱讀 5894

暫無鏈結

題目描述

在2023年,若干火星探險隊探索了這顆紅色行星的不同區域並且製作了這些區域的地圖。現在,baltic空間機構有乙個雄心勃勃的計畫,他們想製作一張整個行星的地圖。為了考慮必要的工作,他們需要知道地圖上已經存在的全部區域的大小。你的任務是寫乙個計算這個區域大小的程式。

具體任務要求為:

(1)從輸入中讀取地圖形狀的描述;

(2)計算地圖覆蓋的全部的區域;

(3)輸出探索區域的總面積(即所有矩形的公共面積)。

輸入格式

輸入的第一行包含乙個整數n(1

≤n≤10000

) (1≤

n≤10000

),表示可得到的地圖數目。

以下n行,每行描述一張地圖。每行包含4個整數x1,y1,x2和y2(0≤

x1<x

2≤30000

0 ≤x

1<x2

≤30000

,0≤y1<y

2≤30000

0 ≤y

1<y2

≤30000

)。數值(x

1,y1

) (x1

,y1)

和(x2,y2

) (x2

,y2)

是座標,分別表示繪製區域的左下角和右上角座標。每張地圖是矩形的,並且它的邊是平行於x座標軸或y座標軸的。

輸出格式

輸出檔案包含乙個整數,表示探索區域的總面積(即所有矩形的公共面積)。

輸入樣例

2 10 10 20 20

15 15 25 30

輸出樣例

解題分析:

赤裸裸的掃瞄線…和視窗的星星的思路一樣, 將x座標離散化, 將上下底按y軸座標排序, 用線段樹維護當前存在的矩形下底。

我們可以將下底權值設為1,上底權值設為-1, 每次更新線段樹區間後將面積加上當前可用的下底乘上與下一條底邊間高度的差。le

n len

表示當前區間可用的總長度, 以及另乙個值va

lid val

id表示當前區間是否可用。我們每次更新(加入一條新的邊)時就更新根據valid值更新。有三種情況:1.v

alid

!=0 val

id!=

0:說明當前區間可用, 所以當前區域的可用底邊長度即為xr

ight

−xle

ft−1

x ri

ght−

xlef

t−12.v

alid

=0v al

id=0

且lef=ri

g lef

=rig

:說明當前點已沒有線段覆蓋,可用長度為0。

3.其他情況:即le

f!=r

igl ef

!=ri

g且va

lid=

0 val

id=0

, 說明之前可能有modify到更小子區域的情況,(在這裡valid並不是向上傳導的), 所以當前區域的可用底邊長度為le

n(so

nlef

t)+l

en(s

onri

ght)

l en

(son

left

)+le

n(so

nrig

ht)。這個性質的前提是:因為每條下底都有對應的上底, 所以當上底加入時區間中還有可能有可用的區間底邊,且不會與抵消了的下底重複, 因為加入下底的時候並沒有將le

n len

下傳到下一層的點, 下一層的len只可能是其他邊賦上的。

下面上**:

#include 

#include

#include

#include

#include

#include

#define r register

#define gc getchar()

#define w while

#define in inline

#define mx 50005

#define db double

template

in void in(t &x)

}namespace sgt

data[mx << 1], anti[mx << 1];

in bool cmp_x (const edge &x, const edge &y)

in bool cmp_y (const edge &x, const edge &y)

//在這裡和視窗的星星一題不同的是, 其實不必將負值的邊排在前面,因為有多條邊的時候它們之間的高為0

in bool

operator == (const edge &x, const edge &y)

struct node

tree[mx << 1];

void build(int now, int l, int r)

in void pushup(const

int &now)

void modify(const

int &now, const

int &lb, const

int &rb, const

int &delta)

int mid = (tree[now].lef + tree[now].rig) >> 1;

if(mid >= rb) modify(ls, lb, rb, delta);

else

if(mid < lb) modify(rs, lb, rb, delta);

else

pushup(now);

}}using

namespace sgt;

using

std::sort;

using

std::unique;

int main()

sort(data + 1, data + 1 + tot, cmp_x);

sort(anti + 1, anti + 1 + tot, cmp_y);

for (r int i = 1; i <= tot; ++i)

build(1, 1, cnt);

int ans = 0;

for (r int i = 1; i < tot; ++i)

printf("%d", ans);

return

0;}

火星探險問題

乙個點同一時間只有一輛車,這個條件並沒有用 因為你可以一輛車一輛車走 於是這個題就和深海機械人問題一樣了,只需要把乙個位置拆成兩個點就好了 輸出方案就dfs一下,記乙個陣列,每次搜過它就 如果等於這條邊流過的流量就不能走 然後就沒了記得檢查陣列大小,不然wa兩遍還不知道陣列開小了 include d...

火星探險問題

7月倒數第二天補flag 拆點,像深海機械人問題一樣。最後求路線的時候dfs一下,根據流量判定走了幾個機械人,不能超過流量即可。include include include include using namespace std const int inf 0x3f3f3f3f,n 5000005...

洛谷 P3356 火星探險問題

給出一張地圖,上面有一些石塊或障礙,現在有一些運載車從左上角出發,要去右下角,只能向右或向下走,每個石塊只能收集一次,輸出收集到最多石塊的路徑.多個運載車,不難想到是網路流,但難點在於每個石塊最多收集一次,而且要收集最多石塊.可以用費用流來做,每個點拆成兩個入點向出點連一條流量為inf,費用為0的邊...