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 ;
}