P1502 窗口的星星
对于一颗星星
(
x
,
y
)
(x,y)
(x,y) ,考虑要包含这颗星星,窗口右端点的范围,实际上是一个矩形:
(
(
x
∼
x
+
w
)
,
(
y
∼
y
+
h
)
)
((x∼x+w),(y∼y+h))
((x∼x+w),(y∼y+h)) ,因为不能在边框上,所以都是开区间。那么实际上就是每个点都给一块矩形加上了
l
i
l_i
li 的权值,然后求权值最大的点的权值是多少。一看,实际上是遍历了所有矩形的并集,那么就想到用扫描线去解决。但是这里的开区间不好处理,所以我们可以把这个矩形的范围替换成这样:
(
(
x
+
0.5
∼
x
+
w
−
0.5
)
,
(
y
+
0.5
∼
y
+
h
−
0.5
)
)
((x+0.5∼x+w-0.5),(y+0.5∼y+h-0.5))
((x+0.5∼x+w−0.5),(y+0.5∼y+h−0.5)) 。我们可以发现,这样替换之后,并未对矩形的并集造成影响。所以我们处理出每个矩形,进行离散化后做扫描线,线段树就只有区间加和询问区间最大值两个操作,而且区间最大值也就是根节点,不用再单独写函数询问。这里的扫描线实际上就是以不断以某区域的底边为代表,询问了区间最大值,实际上询问了一个二维平面的最大值。
#include <bits/stdc++.h>
#define lson rt<<1
#define rson (rt<<1)|1
using namespace std;
const int N = 1e4 + 5;
typedef long long ll;
struct line {
double l; double r; double h; ll v;
};
vector<line> seg;
int n, w, h, tot;
ll tree[N << 4], lz[N << 4];
double x[N << 1];
bool cmp(line a, line b) {
if (a.h == b.h) return a.v > b.v;
return a.h < b.h;
}
void push_down(int rt) {
if (!lz[rt]) return ;
lz[lson] += lz[rt]; lz[rson] += lz[rt];
tree[lson] += lz[rt]; tree[rson] += lz[rt];
lz[rt] = 0;
}
void update(int rt, int l, int r, int L, int R, ll v) {
if (L <= l && r <= R) {
tree[rt] += v;
lz[rt] += v;
return ;
}
push_down(rt);
int mid = l + r >> 1;
if (mid >= L) update(lson, l, mid, L, R, v);
if (mid < R) update(rson, mid + 1, r, L, R, v);
tree[rt] = max(tree[lson], tree[rson]);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int T;
scanf("%d", &T);
while(T--) {
memset(tree, 0, sizeof tree);
memset(lz, 0, sizeof lz);
tot = 0;
seg.clear();
scanf("%d%d%d", &n, &w, &h);
for (int i = 1, xx, yy, ll; i <= n; ++i) {
scanf("%d%d%d", &xx, &yy, &ll);
double L = xx + 0.5, R = xx + w - 0.5;
x[++tot] = L;
x[++tot] = R;
seg.push_back({L, R, yy + 0.5, ll});
seg.push_back({L, R, yy + h - 0.5, -ll});
}
sort(x + 1, x + 1 + tot);
sort(seg.begin(), seg.end(), cmp);
tot = unique(x + 1, x + 1 + tot) - x - 1;
ll ans = 0;
for (int i = 0; i < (int)seg.size(); ++i) {
int L = lower_bound(x + 1, x + 1 + tot, seg[i].l) - x;
int R = lower_bound(x + 1, x + 1 + tot, seg[i].r) - x;
update(1, 1, tot, L, R, seg[i].v);
if (i == (int)seg.size() - 1 || (seg[i].h == seg[i + 1].h && seg[i].v > 0 && seg[i + 1].v < 0) || (seg[i].h != seg[i + 1].h && seg[i].v > 0)) {
ans = max(ans, tree[1]);
}
}
printf("%lld\n", ans);
}
}