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;
}

posted @ 2025-04-28 22:08  Hootime  阅读(9)  评论(0)    收藏  举报