Solution - P1502 窗口的星星
多测不清空,爆零两行泪。
Multiple tests without reset, zero points with double regret.
思路
简单扫描线板子,个人认为比 P5490 【模板】扫描线 & 矩形面积并 简单。
介绍一个在扫描线中常见的技巧:不含边界的时候在边界上减去 \(0.5\) 就可以含边界了。
做法显然,直接维护线段树即可。略。
于是,没了。
代码
#include <bits/stdc++.h>
#define rint register int
#define rllong register long long
#define llong long long
#define N 100005
using namespace std;
struct Node{
int l, r, h, val;
bool operator<(Node a){return h==a.h ? val>a.val : h<a.h;}
} a[N<<1];
int tmp[N<<1], n2, cnt;
int n, w, h, ans;
int val[N<<3], tag[N<<3];
#define mid (l+r>>1)
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define pushup(x) (val[x] = max(val[ls(x)], val[rs(x)]))
inline void build(rint x, rint l, rint r){
val[x] = tag[x] = 0;
if(l == r) return;
build(ls(x), l, mid );
build(rs(x), mid+1, r);
return;
}
inline void pushdown(rint x){
if(!tag[x]) return;
val[ls(x)] += tag[x], val[rs(x)] += tag[x];
tag[ls(x)] += tag[x], tag[rs(x)] += tag[x];
tag[x] = 0;
return;
}
inline void modify(rint x, rint L, rint R, rint l, rint r, rint k){
if(L <= l && R >= r){
val[x] += k, tag[x] += k;
return;
}
pushdown(x);
if(L <= mid) modify(ls(x), L, R, l, mid, k);
if(R > mid) modify(rs(x), L, R, mid+1, r, k);
pushup(x);
return;
}
int _main(){
n2 = cnt = ans = 0;
scanf("%d %d %d", &n, &w, &h);
for(rint i = 1; i <= n; ++i){
rint x, y, val;
scanf("%d %d %d", &x, &y, &val);
a[++cnt] = {x, x+w-1, y, val};
a[++cnt] = {x, x+w-1, y+h-1, -val};
tmp[++n2] = x, tmp[++n2] = x+w-1;
}
sort(tmp+1, tmp+n2+1), n2 = unique(tmp+1, tmp+n2+1)-tmp-1;
for(rint i = 1; i <= cnt; ++i){
a[i].l = lower_bound(tmp+1, tmp+n2+1, a[i].l)-tmp;
a[i].r = lower_bound(tmp+1, tmp+n2+1, a[i].r)-tmp;
}
sort(a+1, a+cnt+1);
build(1, 1, n2);
rint i = 1, j = 1;
for(rint i = 1; i <= cnt; ++i){
modify(1, a[i].l, a[i].r, 1, n2, a[i].val);
ans = max(ans, val[1]);
}
printf("%d\n", ans);
return 0;
}
int t;
int main(){
scanf("%d", &t);
while(t--) _main();
return 0;
}

浙公网安备 33010602011771号