【题解】luoguP1502 窗口的星星
作者:互联网
链接(原本那么长的题面描述呢?)
扫描线线段树的理解,点坐标与区间段的转化处理
首先考虑将“矩形覆盖点”转化成“点在矩形内”;考虑对于点 (x, y) ,会对矩形左下角位于 (x, y) 到 (x+W, y+H) 时产生贡献,于是就转化过来了
然后考虑烦人的“边框上不计算在内”怎么处理,显然由于给出数据都是整数,矩形放置在非整点位置不会产生更优的答案;
那么对于点与区间的处理,令下标 x 表示区间 [x, x+1) ,那么对于 (x, y) ,将会对左下角在网格坐标 [x, y] 到 [x+W-1, y+H-1] 的矩形产生贡献
那么对于自下而上的扫描线,我们令 { [x, x+W-1], y } +c ,令 { [x, x+W-1], y+H } -c 即可
离散化的细节见代码,好像大同小异
然后是扫描线线段树,维护东西可能不一样,但都有一个相同的特征:区间加与区间减是一一对应的
于是所谓 tag ,其实我们只需要把它放在节点头上就行了,不需要也不能 pushdown ,等会自然会把这段的所有 tag 回收掉;至于统计,沿途加 tag 就行了
所以代码很短,有点像是利用线段树进行区间拆分的分块?(
以下定义, tag 表示该点代表的区间,未被执行的操作
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 40005;
int T, N; ll W, H;
struct node {
ll x, y, c; int id;
} P[MAXN<<1];
struct line {
ll l, r, h, c;
} L[MAXN];
ll max(ll x, ll y) { return x > y ? x : y; }
struct segmentTree {
#define lson (x<<1)
#define rson (x<<1|1)
ll maxv[MAXN<<2], tag[MAXN<<2];
void clear() {
memset(maxv, 0, sizeof(maxv));
memset(tag, 0, sizeof(tag));
}
void pushup(int x) {
maxv[x] = max(maxv[lson], maxv[rson]) + tag[x];
}
void update(int x, int l, int r, int _l, int _r, ll k) {
if (l>=_l && r<=_r) { tag[x] += k, pushup(x); }
else {
int mid = (l + r) >> 1;
if (mid>=_l) update(lson, l, mid, _l, _r, k);
if (mid< _r) update(rson, mid+1, r, _l, _r, k);
pushup(x);
}
}
} ST;
void addn(int i, ll xx, ll yy, ll cc, int dd)
{
P[i].x = xx, P[i].y = yy, P[i].c = cc, P[i].id = dd;
}
int cmp1(node a, node b) { return a.x < b.x; }
int cmp2(node a, node b) { return a.id==b.id ? a.x<b.x : a.id<b.id; }
int cmp3(line a, line b) { return a.h < b.h; }
int main()
{
scanf("%d", &T);
for (; T; T--) {
scanf("%d%lld%lld", &N, &W, &H);
for (int i=1; i<=N; i++) {
ll x, y, z; scanf("%lld%lld%lld", &x, &y, &z);
addn(i, x, y, z, i);
addn(i+N, x+W-1, y, z, i);
addn(i+N*2, x, y+H, -z, i+N);
addn(i+N*3, x+W-1, y+H, -z, i+N);
}
sort(P+1, P+N*4+1, cmp1);
int tot = 1;
for (int i=1; i< N*4; i++) {
int t = tot + (P[i+1].x> P[i].x);
P[i].x = tot, tot = t;
}
P[N*4].x = tot;
sort(P+1, P+N*4+1, cmp2);
for (int i=1; i<=N*4; i+=2) {
L[P[i].id].l = P[i].x, L[P[i].id].r = P[i+1].x;
L[P[i].id].h = P[i].y, L[P[i].id].c = P[i].c;
}
sort(L+1, L+N*2+1, cmp3);
ST.clear();
int p = 0; ll ans = 0;
for (int i=1; i<=N*2; i++) {
while (p< N*2 && L[p+1].h< L[i].h+H) {
p++;
ST.update(1, 1, tot, L[p].l, L[p].r, L[p].c);
}
ans = max(ans, ST.maxv[1]);
}
printf("%lld\n", ans);
}
}
标签:星星,node,int,题解,luoguP1502,mid,id,tag,ll 来源: https://www.cnblogs.com/zhyh/p/15144211.html