POJ 2482 stars in your window(线段树 , 扫描线)

题目大意:

  给你10000以内的星星的坐标和亮度,让你用一个W × H 的矩形去围住一个区域,使得区域内星星的亮度最大,矩形边缘上的星星不算。

解题思路:

 对于每一个星星 建立一个(x, y , y + h , c) 的扫描线 和一个(x + w , y , y + h , - c)的扫描线,将问题转化成求区间最大值。几个需要注意的地方:矩形边缘上的需要处理一下,将每个叶节点设为长度为1的线段。另外此题如果用long long wa掉的话可以改为unsigned.

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <set>
#define LL unsigned
#define FOR(i,x,y) for(LL i=x;i<=y;i++)
#define rFor(i,x,y) for(LL i=x;i>=y;i--)
#define lson l , m , rt<<1
#define rson m , r , rt<<1|1
using namespace std;
const LL MAXN = 222222;
LL X[MAXN<<2];
int cnt[MAXN<<2] , MAX[MAXN<<2];
struct Seg
{
	LL h , l , r;
	int val;
	Seg() { }
	Seg(LL a , LL b , LL c , int d) : h(a) , l(b) , r(c) , val(d) { }
	bool operator < (const Seg& rhs) const
	{
		return h < rhs.h || (h == rhs.h && val < rhs.val);
	}
}ss[MAXN];
void pushdown(int rt)
{
	if(cnt[rt])
	{
		cnt[rt<<1] += cnt[rt];
		cnt[rt<<1|1] += cnt[rt];
		MAX[rt<<1] += cnt[rt];
		MAX[rt<<1|1] += cnt[rt];
		cnt[rt] = 0;
	}
}
void pushup(int rt)
{
	MAX[rt] = max(MAX[rt<<1] , MAX[rt<<1|1]);
}
void build(int l , int r , int rt)
{
	MAX[rt] = 0 ; cnt[rt] = 0;
	if(l + 1 == r) return ;
	int m = (l + r) >> 1;
	build(lson);
	build(rson);
}
void update(int L , int R , int val , int l , int r , int rt)
{
	if(L <= l && R >= r)
	{
		cnt[rt] += val;
		MAX[rt] += val;
		return ;
	}
	pushdown(rt);
	int m = (l + r) >> 1;
	if(L < m) update(L , R , val , lson);
	if(R > m) update(L , R , val , rson);
	pushup(rt);
}
int N , W , H;
int main()
{
	while(scanf("%d%d%d",&N , &W , &H) != EOF)
	{
		int m = 0;
		while(N--)
		{
			int x , y ,val;
			scanf("%d%d%d",&x,&y,&val);
			X[m] = y;
			ss[m++] = Seg(x , y , (LL)(y + H) , val);
			X[m] = (LL)(y + H);
			ss[m++] = Seg((LL)(x + W) , y , (LL)(y + H) ,-val);
		}
		sort(X , X + m);
		sort(ss , ss + m);
		int k = 1;
		for(LL i = 1 ; i < m ; i ++)
			if(X[i] != X[i - 1]) X[k++] = X[i];
		memset(cnt , 0 , sizeof(cnt));
		memset(MAX , 0 , sizeof(MAX));
		build(0 , k - 1  , 1);
		int ans = 0;
		for(int i = 0 ; i < m; i++)
		{
			int l = lower_bound(X , X + k , ss[i].l) - X;
			int r = lower_bound(X , X + k , ss[i].r) - X ;
			update(l , r , ss[i].val , 0 , k - 1 , 1);
			ans = max(ans , MAX[1]);
		}
		printf("%d\n",ans);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值