題意:
矩形周長並(輪廓線長度)
思路:我們可以分開求,周長分為x軸上的和y軸上的
從下往上掃瞄,首先看x軸的邊,第一條邊我們可以直接加出貢獻,如果第二條邊我們和第一條有覆蓋部分,那麼我們要怎麼加呢,我們會發現要加的也就是 ( 加入這條邊後的有效長度和沒加之前的有效長度的差值),只要加入一條邊使得整個有效長度變化了(變大或變小),都說明它沒有被其他邊完全覆蓋掉,它有一部分是露出來的,所以它對總周長是有貢獻的。
y軸同理,那就可以從下到上掃瞄一遍,從左向右再掃瞄一遍來做,這是第一種做法。
第二種就是只掃瞄一遍。從下往上掃瞄,x軸方向的邊用上面的方法就可以,關鍵是如何在縱向掃瞄的同時統計出y軸的資訊。可以發現,縱向掃瞄的時候,矩形塊被分成了很多「橫條」,每個橫條的高度好求(相鄰邊的高度差),關鍵是有幾條是有效的周長,我們很容易直觀的想到,最外面的肯定就是有效的周長,那麼裡面的呢?仔細一想可以知道,如果兩個區間,3種情況如下:
兩條綠線是相鄰的掃瞄線劃分成的橫條,對號表示是有效周長,×表示不是。
只要判斷兩個區間的邊界是否重合即可,用lbd和rbd分別來記錄。
// 求矩形並的周長(輪廓線長度)
#include #include #include #define lson l, mid, root<<1
#define rson mid, r, root<<1|1
using namespace std;
const int inf = 0x3f3f3f3f;
typedef long long ll;
const int maxn = 10000+5;
int x[maxn];
// 矩形的邊
struct edge
edge(int a, int b, int c, int d):l(a),r(b),h(c),flag(d){}
bool operator < (const edge& rhs) const
}edges[maxn];
// 線段樹節點
struct nodetree[maxn<<2];
void stree_build(int l, int r, int root)
void push_up(int l, int r, int rt)
else if(l+1 == r)
else
}void update(int la, int rb, int l, int r, int root, int val)
if(l+1 == r) return;
int mid = (l+r) >> 1;
if(la < mid) update(la, rb, lson, val);
if(rb > mid) update(la, rb, rson, val);
push_up(l, r, root);
}int main()
//printf("tot = %d\n", tot);
sort(edges+1, edges+tot+1);
sort(x+1, x+tot+1);
int k = 1;
for(int i = 2; i <= tot; ++i) if(x[i] != x[i-1]) x[++k] = x[i];
stree_build(1, k, 1);
int ans = 0, last = 0;
for(int i = 1; i <= tot; ++i)
printf("%d\n", ans);
} return 0;
}
HDU 1828 Picture 線段樹 掃瞄線
題意 給你一些矩形的左上角點的座標和右下角點的座標,求周長並 最顯而易見的思路就是對於x軸和y軸做兩次掃瞄線,對於負數的座標進行離散化。每次增加的值是線段變化量的絕對值。具體寫法和求面積並的差不多。include include include include using namespace std...
hdu1828線段樹 掃瞄線
矩形求周長類似矩形合併求面積,只是多了需要統計豎邊的個數,對於每次求到的下底邊長還要增加目前底邊與下一條底邊之間的豎邊總長 1,n個矩形有2 n條線段,按從小到大排列,如上圖得到的線段順序 開始掃瞄第一條線段,得到總底邊長sum為a這部分,得到豎邊個數segnum 2,每增加一條底邊segnum 2...
HDU 1828 掃瞄線求周長
思路 可以使用1條掃瞄線.從下往上我掃,在掃的過程中,周長就是下面的橫座標的投影加上上下兩條座標之差乘上縱座標線段數 需要注意重邊 include include include include include include include include include include defi...