如果仔細觀察掃瞄器工作就會發現,掃瞄器掃瞄時是一條線從頭到尾掃一遍成像。這個演算法形象化表示也是如此。
首先是掃瞄線板子題:矩形面積並。
題意:在平面直角座標系中,給出若干個矩形,求所有矩形的面積並。
太長不看版:對於所有矩形的端點按照縱座標排序,然後依次掃瞄矩形每加入一條線段覆蓋,線段樹查詢所有區間中覆蓋的長度即可。
詳細來說,就是我們對每個矩形進行抽象化處理,把矩形的水平兩條邊單獨拿出來,記錄這條邊的左右端點和高度。並且給這條邊賦上乙個特殊的值,為+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代表該區間內被覆蓋的線段...