线段树-poj2482矩形框星星

#include <iostream>
#include <stdio.h>
#include <bits/stdc++.h>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define  inf  0x1fffffff
#define maxn 20007
#define LL long long
using namespace std;
//SBT 离散化 
LL Rank[maxn], Rn;
void SetRank() {         //相当于unique
	sort(Rank + 1, Rank + 1 + Rn);//先排序
	int I = 1;
	for (int i = 2; i <= Rn; ++i) if (Rank[i] != Rank[i - 1]) Rank[++I] = Rank[i];//不重复的放进去 
	Rn = I;
}
int GetRank(LL x) {
	int L = 1, R = Rn, M;//[L,R] first >=x
	while (L != R) {
		M = (L + R) >> 1;
		if (Rank[M] < x) L = M + 1;
		else R = M;
	}
	return L;
}
//储存数据 
struct Star {//记录星星,之后要排序 
	LL x, y; int c;
	Star() {}
	Star(LL x, LL y, int c) :x(x), y(y), c(c) {}
	bool operator < (const Star& B)const {
		return x < B.x || x == B.x && y < B.y;
	}
}St[maxn >> 1];
int n, W, H;
//线段树 区间加&&最大值 
int Max[maxn << 2], Add[maxn << 2];
void PushUp(int rt) {
	Max[rt] = max(Max[rt << 1], Max[rt << 1 | 1]);
}
void PushDown(int rt) {
	if (Add[rt]) {
		Add[rt << 1] += Add[rt]; Add[rt << 1 | 1] += Add[rt];
		Max[rt << 1] += Add[rt]; Max[rt << 1 | 1] += Add[rt];
		Add[rt] = 0;
	}
}
void Update(int L, int R, int C, int l, int r, int rt) {
	if (L <= l && r <= R) { Add[rt] += C; Max[rt] += C; return; }
	PushDown(rt);
	int m = (l + r) >> 1;
	if (L <= m) Update(L, R, C, l, m, rt << 1);
	if (R > m) Update(L, R, C, m + 1, r, rt << 1 | 1);
	PushUp(rt);
}
int main(void)
{
	while (cin>>n>>W>>H)) {
		memset(Max, 0, sizeof(Max));
		memset(Add, 0, sizeof(Add));
		Rn = 0;
		for (int i = 1; i <= n; ++i) {
			cin>>St[i].x>>St[i].y>>St[i].c;
			Rank[++Rn] = St[i].y;
			Rank[++Rn] = St[i].y + H;     //存入纵坐标
		}
		SetRank();
		sort(St + 1, St + n + 1);//给星星排序     
		int L = 1, X, ANS = 0;
		for (int i = 1; i <= n; ++i) {
			Update(GetRank(St[i].y), GetRank(St[i].y + H) - 1, St[i].c, 1, Rn, 1);//加入新矩形  
			X = St[i].x;//更新当前X 星星的横坐标
			while (St[L].x + W <= X) {//删除已经对横坐标为X的扫描线无影响的矩形 
				Update(GetRank(St[L].y), GetRank(St[L].y + H) - 1, -St[L].c, 1, Rn, 1);
				++L;
			}
			ANS = max(ANS, Max[1]);//求最大值 
		}
		printf("%d\n", ANS);//输出答案 
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值