poj 2482 Stars in Your Window

本文介绍了一种使用线段树数据结构解决矩形区域亮度计算问题的方法。通过将每个矩形中心视为基准点,并建立边界线,实现对区域内亮度的最大覆盖次数计算。

我用上一道题的方法把这个题A掉了。。。

记得这题是做之前寒假后学树状数组碰到的,但是没做。

前天比赛也想到这题了,没往深处想,以为不一样呢(因为当时很坚定我的想法呐。。。)

赛后看了这个题,基本是一样了,比赛那题两个点可以重复,而且边缘的点也算,这个的话不是。

依旧老做法,把每个点作为矩形的中心,建立两条边界线。因为边界重合不算,那么如果x相同的话,负的那条线应该排前面。然后插入删除线段神马的。计算线段最大覆盖次数即可。亮度用线段的权值表示。

依旧更新到底了。可以不更新到底的,记录当前加的数和当前区间的max即可。

250ms,不怎么快。

想想用树状数组应该怎么做呢。(貌似不能用树状数组)。

————————————————————————————————————————————————————————

悲剧啊,看网上代码,貌似想法和我的一样哎。。难道这就是这题的标准解?? = =。。。

只不过好多都是以星星为左下角做的,其实是一样的。

不过是以左下角了,可以避免用double ,不过得用long long了。

下面代码是以左下角的。这种转化的思想很强大呢。


#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define FOR(i,s,t) for(int i=s; i<t; i++)
#define BUG puts("here!!!")  
#define STOP system("pause")
using namespace std;  
const int MAX = 20010;  
struct point {int x,y; long long lx, ly, rx, ry; int val;};
point p[MAX/2];
long long x[MAX], y[MAX];
int ans; 
struct Sline{int x,y1,y2;int flag;};
Sline l[MAX];
void add_line(int x1, int y1, int x2, int y2,int &cnt,int flag)
{
	l[cnt].x = x1; l[cnt].y1 = y1; l[cnt].y2 = y2;
	l[cnt++].flag = flag;
	l[cnt].x = x2; l[cnt].y1 = y1; l[cnt].y2 = y2;
	l[cnt++].flag = -flag;
}
bool cmp(Sline a,Sline b)
{
	if( a.x == b.x ) return a.flag < b.flag;
	return a.x < b.x;
}
struct Tnode{				// 一维线段树 
    int l,r,val,max;
    int len() { return r - l;}
    int mid() { return MID(l,r);}
    bool in(int ll,int rr) { return l >= ll && r <= rr; }
    void lr(int ll,int rr){ l = ll; r = rr;}
};
Tnode node[MAX<<2];
void Build(int t,int l,int r)
{
	node[t].val = node[t].max = 0;
	node[t].lr(l,r);
	if( node[t].len() == 1 ) return ;
	int mid = MID(l,r);
	Build(L(t),l,mid);
	Build(R(t),mid,r);
}
void Updata(int t,int l,int r,int val)
{	
	if( node[t].in(l,r) )
	{
		node[t].val += val;
		node[t].max += val;
		ans = max(node[t].max, ans);
		return ;
	}
	if( node[t].len() == 1 ) return ;	
	node[L(t)].val += node[t].val;
	node[L(t)].max += node[t].val;
	node[R(t)].val += node[t].val;
	node[R(t)].max += node[t].val;
	node[t].val = 0;
	int mid = node[t].mid();
	if( l >= mid )
		Updata(R(t),l,r,val);
	else
		if( r <= mid )
			Updata(L(t),l,r,val);
		else
		{
	 		Updata(L(t),l,r,val);
 			Updata(R(t),l,r,val);
		}
	node[t].max = max(node[L(t)].max, node[R(t)].max);
	ans = max(node[t].max, ans);
}
  
int solve(int cx, int cy, int n)
{
	sort(x, x+cx);
	sort(y, y+cy);
	cx = unique(x, x+cx) - x;
	cy = unique(y, y+cy) - y;
	int cnt = 0;
	FOR(i, 0, n)
	{
		int x2 = lower_bound(x, x+cx, p[i].rx) - x;
		int y2 = lower_bound(y, y+cy, p[i].ry) - y;
		int x1 = lower_bound(x, x+cx, p[i].lx) - x;
		int y1 = lower_bound(y, y+cy, p[i].ly) - y;
		add_line(x1, y1, x2, y2, cnt, p[i].val);
	}
	sort(l, l+cnt, cmp);
	Build(1, 0, cy+1);
	FOR(i, 0, cnt)
		Updata(1, l[i].y1, l[i].y2, l[i].flag);
	return ans;
}
	
int main()  
{  
    int l;
	int n, w;
	while( scanf("%d%d%d", &n, &w, &l) != EOF )
	{
		int cntx = 0, cnty = 0;
		ans = 0;
		FOR(i, 0, n)
		{
			scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].val);
			p[i].lx = p[i].x; p[i].ly = p[i].y;
			p[i].rx = p[i].x*1ll + w; p[i].ry = p[i].y*1ll + l;
			x[cntx++] = p[i].lx;
			x[cntx++] = p[i].rx;
			y[cnty++] = p[i].ly;
			y[cnty++] = p[i].ry;
		}
		solve( cntx, cnty, n);
		printf("%d\n",ans);
	}

return 0;  
}  


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值