這道題還耗了我很久的時間,因為不懂得掃瞄線到底要怎麼做而一直翻了很多dalao的題解。
這道題求的是乙個指定大小的矩形可以框住多少顆星星,他們的亮度總和最大。
直接移動矩形不可行,我們將每顆星星轉換為每顆星星能被矩形框住的響應區域,不難發現也是矩形。
為了不重複計算,我們只考慮在右上區域框住星星,不然會算重。
所以問題成功轉換為:求最大的矩形的交,使相應面積最大。
這個時候就可以使用掃瞄線了。
可以從下往上掃瞄,每一次記錄乙個矩形的下邊,加入一條線,加上附帶的資訊比如左右端點和更新答案值。
如何有順序地掃瞄?直接用排序排一下就可以了。
思想很容易懂,但是如何使用**實現?
我們使用乙個結構體名字叫line,記錄y軸,左右端點和對答案的貢獻。
顯然碰到矩形的下邊,我們對答案就要區間加了,而碰到上邊就要區間減了。
最後還要維護全域性的最大值,可以直接寫乙個線段樹模板化地維護。
然後還出了個鍋:初始化全域性任何元素都是0!連build都不用!
**:
#include#include#includeconst int maxn = 100005;
const int inf = 0x3f3f3f3f;
struct line
line[maxn];
int ls[maxn];
int a[maxn], tot;
int n, w, h, ans;
struct segtree
void pushup(int root)
/*void build(int root, int l, int r)}*/
void pushdown(int root, int l, int r)
}void update(int root, int l, int r, int x, int y, int k)
pushdown(root, l, r);
int mid = (l + r) >> 1;
update(lson, l, mid, x, y, k);
update(rson, mid + 1, r, x, y, k);
pushup(root);
}int query(int root, int l, int r, int x, int y)
} seg;
bool cmp(line a, line b)
int read()
while(ch >= '0' && ch <= '9') ans = (ans << 3) + (ans << 1) + ch - '0', ch = getchar();
return s * ans;
}void init()
int main()
std::sort(ls + 1, ls + n + n + 1);
a[++tot] = ls[1];
for(int i = 2; i <= n + n; i++)
std::sort(line + 1, line + n + n + 1, cmp);
1, tot);
for(int i = 1; i <= n + n; i++)
printf("%d\n", ans);
}return 0;
}
P1502 視窗的星星(掃瞄線入門第一題)
提交2.78k 通過682 時間限制1.00s 記憶體限制125.00mb 提交 加入收藏 題目提供者cyrcyr 難度省選 noi 歷史分數100 提交記錄 檢視題解 高效能高階資料結構 檢視演算法標籤 進入討論版 檢視討論 檢視推薦 展開小卡買到了一套新房子,他十分的高興,在房間裡轉來轉去。晚上...
Luogu 1502 視窗的星星 題解 掃瞄線
其實一眼看不出掃瞄線。我們可以把每乙個點都變成乙個長寬為w和h的矩形。左邊的邊是 w,右邊的邊是 w。線段樹維護區間max和lazy tag。然後掃瞄線求max。如下 include define ll long long using namespace std const int maxn 200...
P3353 在你窗外閃耀的星星
飛逝的的時光不會模糊我對你的記憶。難以相信從我第一次見到你以來已經過去了3年。我仍然還生動地記得,3年前,在美麗的集美中學,從我看到你微笑著走出教室,你將頭向後仰,柔和的晚霞照耀著你玫瑰色的臉頰。我明白,我已經沉醉於你了。之後,經過幾個月的觀察和窺探,你的優雅與智慧型,你對待生活的態度和你對未來的願...