题目传送门。
思路
扫描线
扫描线
首先,将题目中给出的条件和问题进行转化:
首先先不考虑边框上的点不算在内的限制,考虑一个点可以对那些矩形产生贡献。
只考虑矩形的右上角,容易发现,每个星星的亮度只对右上角在以星星为左下角的长为 \(W\),高为 \(H\)的矩形有贡献。
如图。
那么便可以把问题进行转化:在平面直角坐标系上有 \(n\) 个有权值矩形,求他们最大的重合的权值。
于是就可以用扫描线来解决了。
再考虑边框上的点不算在内的限制,因为可以这样框:
有效的矩形就相当于 \(W - 1\),\(H - 1\) 的能取边框上的点的矩形,然后像上面那样做就可以了。
细节
对线进行排序时,要注意若两条线重合,应按权值从大到小排序。
因为可能两个矩形贴合,而又能取矩形边框上的点,所以不排序的话权值可能算小。
点击查看代码
代码
/*--------------------------------| code by FRZ_29 || code time || 2024/08/11 || 11:02:16 || 星期天 |--------------------------------*/#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
typedef long long LL;using namespace std;void RD() {}
template<typename T, typename... U> void RD(T &x, U&... arg) {x = 0; LL f = 1;char ch = getchar();while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();x *= f; RD(arg...);
}const LL N = 1e4 + 5;#define LS (rt << 1)
#define RS (rt << 1 | 1)
#define MID (l + r >> 1)
#define LF(i, __l, __r) for (LL i = __l; i <= __r; i++)
#define RF(i, __r, __l) for (LL i = __r; i >= __l; i--)struct tree{LL l, r, mx, add;tree(LL l = 0, LL r = 0, LL mx = 0, LL add = 0) : l(l), r(r), mx(mx), add(add) {}
} tr[N << 4];
struct seg {LL l, r, h, val;seg(LL l = 0, LL r = 0, LL h = 0, LL val = 0) : l(l), r(r), h(h), val(val) {}
} a[N << 1];
LL t, n, w, h, Y[N << 1];void up(LL rt) { tr[rt].mx = max(tr[LS].mx, tr[RS].mx); }
bool cmp(seg a, seg b) { return (a.h != b.h ? a.h < b.h : a.val > b.val); }void Init() {memset(a, 0, sizeof(a));memset(tr, 0, sizeof(tr));
}void build(LL rt, LL l, LL r) {tr[rt] = tree(l, r, 0LL, 0LL);if (l == r) return;build(LS, l, MID), build(RS, MID + 1, r);
}void down(LL rt) {tr[LS].mx += tr[rt].add;tr[RS].mx += tr[rt].add;tr[LS].add += tr[rt].add;tr[RS].add += tr[rt].add;tr[rt].add = 0;
}void update(LL rt, LL L, LL R, LL val) {LL l = tr[rt].l, r = tr[rt].r;if (L <= l && r <= R) {tr[rt].mx += val;tr[rt].add += val;return;}down(rt);if (L <= MID) update(LS, L, R, val);if (R > MID) update(RS, L, R, val);up(rt);
}int main() {RD(t);while (t--) {Init();RD(n, w, h);w--, h--;LF(i, 1, n) {LL x, y, l;RD(x, y, l);Y[2 * i - 1] = y, Y[2 * i] = y + h;a[2 * i - 1] = seg(y, y + h, x, l);a[2 * i] = seg(y, y + h, x + w, -l);}n <<= 1;sort(Y + 1, Y + n + 1);LL len = unique(Y + 1, Y + n + 1) - Y - 1;sort(a + 1, a + n + 1, cmp);LF(i, 1, n) {LL low_l = lower_bound(Y + 1, Y + len + 1, a[i].l) - Y;LL low_r = lower_bound(Y + 1, Y + len + 1, a[i].r) - Y;a[i].l = low_l, a[i].r = low_r;}build(1, 1, len);LL ans = 0;LF(i, 1, n) {update(1, a[i].l, a[i].r, a[i].val);ans = max(ans, tr[1].mx);}printf("%lld\n", ans);}return 0;
}/* * ps:FRZ弱爆了 * 感冒写的代码唐爆了……*/
前尘隔海,古屋不再。