http://poj.org/problem?id=2482
题意:
给你一个二维坐标系,和其中的一些点,这些点每个都有一个自己的value,要求用一个W*H的矩形框 框住尽可能多的点,并且使得被包括的点的values和最大。
思路:
和黑书上的一道例题类似,我们可以先将所有的点分成两个点,一个是原来的点(x,y,v) ,再加一个点(x+W,y,-v),然后将所有的点按照X排序,(这样做的好处是当我们设置一个扫描线从左到右扫描的时候,在扫描线控制的区域(也就是合法的矩形区域内)不能再控制到一个点的时候(也就是这个点的值不能再算在后面的计算中的时候)我们可以及时地将改点“剔除”),然后从左到右设置一个扫描线,每次扫描到一个点,就在Y轴上的y处的值加上一个values, 在y+H处加上一个-values(这样做的好处是控制Y轴方向上的坐标在H范围内,原来和上面所说的控制X轴方向上的范围是一样的)。 最后线段树的节点需要维护一个sum 和max ,分别表示区间内的和,和区间的前缀和。
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
typedef long long LL ;
LL N , W , H ;
const int MAXN = 20050 ;
struct point{
LL x , y , s ;
point(){}
point(LL a, LL b ,LL c)
:x(a),y(b),s(c){}
bool operator< (const point& cmp ) const {
if(x == cmp.x) return s < cmp.s ; //这里需要注意
return x < cmp.x ;
}
}p[MAXN] ;
LL Y[MAXN] ;
LL sum[MAXN<<2] , max[MAXN<<2] ;
LL find(LL l, LL r, LL val ){
while( l<r ){
LL mid = (l + r) >> 1 ;
if( Y[mid] < val ) l = mid + 1;
else r = mid ;
}
return l ;
}
void up(LL l ,LL r, LL idx){
LL ls = idx<<1 , rs = idx<<1|1 ;
sum[idx] = sum[ls] + sum[rs] ;
max[idx] = max[ls] ;
if( max[idx] < sum[ls] + max[rs] )
max[idx] = sum[ls] + max[rs] ;
}
void update(LL l ,LL r, LL idx, LL pos , LL val){
if(l == r){
sum[idx] += val ;
max[idx] += val ;
return ;
}
LL mid = (l + r) >> 1 ;
LL ls = idx<<1 ,rs = idx<<1|1 ;
if( pos<= mid ) update(l ,mid ,ls ,pos , val );
else update(mid+1, r, rs, pos, val );
up(l ,r,idx);
}
void solve(LL m , LL n){
memset(sum , 0 ,sizeof(sum)) ;
memset(max, 0 , sizeof(max)) ;
LL _max = 0 ;
for(LL i=0;i<m;i++){
LL s = find(0 , n , p[i].y ) ;
LL e = find(0 , n , p[i].y+H) ;
if( _max < max[1] ) _max = max[1] ;
update(0 , MAXN , 1 , s , p[i].s ) ;
update(0 , MAXN , 1 , e , -p[i].s ) ;
}
printf("%lld\n",_max);
}
int main(){
LL x, y ,v ;
while( scanf("%lld%lld%lld",&N,&W,&H) == 3){
for(LL i=0;i<N;i++){
scanf("%lld%lld%lld",&x,&y,&v);
p[i<<1] = point(x , y , v);
p[i<<1|1] = point(x+W , y , -v );
Y[i<<1] = y ; Y[i<<1|1] = y + H ;
}
LL m = N<<1 ;
std::sort(Y , Y+m);
std::sort(p , p+m);
LL n = 1 ;
for(LL i=1;i<m;i++){
if( Y[i]!=Y[i-1] ) Y[n++] = Y[i] ;
}
n-- ;
solve( m , n );
}
return 0 ;
}
本文介绍了一种通过将点分为原点和其负值扩展点,按照X轴排序,设置扫描线进行Y轴方向控制,使用线段树维护和计算最大值的方法来解决二维坐标系内最大化矩形框内点的值问题。
1193

被折叠的 条评论
为什么被折叠?



