【POJ2482】Stars in Your Window
【POJ2482】Stars in Your Window
题面
题解
第一眼还真没发现这题居然™是个扫描线
令点的坐标为\((x,y)\)权值为\(c\),则
若这个点能对结果有\(c\)的贡献,必须要矩形左下角的点的范围必须在\(([x,x+w),[y,y+h))\)之间
则按扫描线套路将一个类似矩形的范围拆成线\((x,y1,y2,c)\)、\((x+w,y1,y2,-c)\)(依次表示横坐标、下端点纵坐标、上端点纵坐标、权值)即可
最后注意排序时不但要按\(x\)排,也要按权值排
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAX_N = 100005;
ll N, W, H;
struct rec { ll x, y, _y, k; } t[MAX_N << 1]; int cnt;
inline bool cmp_x (const rec &a, const rec &b) {
if (a.x == b.x) return a.k < b.k;
else return a.x < b.x;
}
ll X[MAX_N << 2], size = 0;
#define lson (o << 1)
#define rson (o << 1 | 1)
ll mx[MAX_N << 3], tag[MAX_N << 3];
void puttag(int o, ll v) { mx[o] += v, tag[o] += v; }
void pushup(int o) { mx[o] = max(mx[lson], mx[rson]) + tag[o]; }
void build(int o, int l, int r) {
mx[o] = tag[o] = 0;
if (l == r) return ;
int mid = (l + r) >> 1;
build(lson, l, mid); build(rson, mid + 1, r);
}
void modify(int o, int l, int r, int ql, int qr, ll v) {
if (ql <= l && r <= qr) return (void)puttag(o, v);
int mid = (l + r) >> 1;
if (ql <= mid) modify(lson, l, mid, ql, qr, v);
if (qr > mid) modify(rson, mid + 1, r, ql, qr, v);
pushup(o);
}
int main () {
while (scanf("%lld%lld%lld", &N, &W, &H) != EOF) {
cnt = 0; size = 0;
for (int i = 1; i <= N; i++) {
ll x, y, c; scanf("%lld%lld%lld", &x, &y, &c);
t[++cnt].x = x, t[cnt].y = y, t[cnt]._y = y + H, t[cnt].k = c;
t[++cnt].x = x + W, t[cnt].y = y, t[cnt]._y = y + H, t[cnt].k = -c;
X[++size] = x, X[++size] = x + W, X[++size] = y, X[++size] = y + H;
}
sort(&X[1], &X[size + 1]); size = unique(&X[1], &X[size + 1]) - X - 1;
sort(&t[1], &t[cnt + 1], cmp_x);
build(1, 1, size - 1);
ll ans = 0;
for (int i = 1; i <= cnt; i++) {
int l = lower_bound(&X[1], &X[size + 1], t[i].y) - X;
int r = lower_bound(&X[1], &X[size + 1], t[i]._y) - X - 1;
modify(1, 1, size - 1, l, r, t[i].k);
ans = max(ans, mx[1]);
}
printf("%lld\n", ans);
}
return 0;
}