掃瞄線 線段樹學習筆記

2022-05-16 11:23:06 字數 1813 閱讀 7634

如果仔細觀察掃瞄器工作就會發現,掃瞄器掃瞄時是一條線從頭到尾掃一遍成像。這個演算法形象化表示也是如此。

首先是掃瞄線板子題:矩形面積並。

題意:在平面直角座標系中,給出若干個矩形,求所有矩形的面積並。

太長不看版:對於所有矩形的端點按照縱座標排序,然後依次掃瞄矩形每加入一條線段覆蓋,線段樹查詢所有區間中覆蓋的長度即可。 

詳細來說,就是我們對每個矩形進行抽象化處理,把矩形的水平兩條邊單獨拿出來,記錄這條邊的左右端點和高度。並且給這條邊賦上乙個特殊的值,為+1或-1,對於矩形下方的邊賦+1,上方的邊賦-1,表示掃瞄過程中進入和離開矩形。然後用乙個線段樹維護區間內的線段長度,再乘上對應高度就行。

然後來一道需要稍稍構造一下的題:

每個人都有乙個能力值ai,而如果兩個人之間的能力值差距過大,那麼兩個人就無法交流,然而每個人的溝通能力也是不同的,具體來講,每個人只能接受能力值在[li,ri]內的人做他的隊友,

想讓隊伍裡的人數盡可能的多,請你輸出這個最多的人數。

我們注意到,假設在隊伍人數最多時,所有的人能接受的區間為[l,r],那麼對每個人來說li <= l <= a,a <= r <= ri,所以我們可以把每個人看成乙個矩形,矩形水平方向邊為[li,ai],豎直方向的邊為[ai,ri],問題就轉化為找到乙個點使得覆蓋這個點矩形數目最多,那就直接掃瞄線,每次掃到一條邊就區間+1或-1,維護區間最大值,就可以了。複雜度o(nlogn)。

#include#include

#include

#include

#include

#include

#include

#include

#define b printf("break\n");

#define a(x) cout << #x << " " << (x) << endl;

#define ll long long

using

namespace

std;

intread()

while(c >= '

0' && c <= '9'

)

return f *x;

}#define n 300010

intans;

struct

rec}rec[n

<< 1

];#define ls x << 1,l,mid

#define rs (x << 1 | 1),mid + 1,r

#define mid ((l + r) >> 1)

int tree[n << 2],lazy[n << 2

];void add(int x,int l,int r,int

k)void push_down(int x,int l,int

r)void modify(int x,int l,int r,int p,int q,int

k) push_down(x,l,r);

if(p <=mid) modify(ls,p,q,k);

if(q >mid) modify(rs,p,q,k);

tree[x] = max(tree[x << 1],tree[x << 1 | 1

]);

return;}

intcnt;

void add(int l,int a,int

r)int

main()

sort(rec + 1,rec + 1 +cnt);

for(int i = 1;i <= cnt;i++)

printf(

"%d\n

",ans);

}

線段樹掃瞄線 學習筆記

見注釋 參考 include include using namespace std const int n 205 struct line line n struct node tr n 2 int n,cnt double fy n xx1,xx2,yy1,yy2 void build int ...

線段樹 掃瞄線學習筆記

之後有一回在luogu做了一道同樣求矩形周長的題,用了下面的模板,但是有組資料過不了,需要做如下修改 過載運算子函式修改成 bool operator const p p const p p int xx,int hh,int juu s maxn 1 void upfather int k,int...

線段樹 掃瞄線

pku 1151 hdu1542 atlantis 矩形面積並 題意 給出n個矩形,每個矩形給出左下角座標,右上角座標。然後求矩形並的總面積 思路 浮點數先要離散化 然後把矩形分成兩條邊,上邊和下邊,對橫軸建樹,然後從下到上掃瞄上去,用cnt表示該區間下邊比上邊多幾個,sum代表該區間內被覆蓋的線段...