其他分享
首页 > 其他分享> > 【题解】luoguP1502 窗口的星星

【题解】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