手机屏摔碎了哦凑。
题意
一个平面里有N(N<10000)个点,每个点 有一个值Vi,用一个长宽为W,H的矩形框,在平面内平移,不能旋转,最多能使框内(不包括边界)的点的V值和为多少 ?
IO
Input
There are several test cases in the input. The first line of each case contains 3 integers: n, W, H, indicating the number of stars, the horizontal length and the vertical height of the rectangle-shaped window. Then n lines follow, with 3 integers each: x, y, c, telling the location (x, y) and the brightness of each star. No two stars are on the same point.
There are at least 1 and at most 10000 stars in the sky. 1<=W,H<=1000000, 0<=x,y<2^31.
Output
For each test case, output the maximum brightness in a single line.
分析
首先要对问题进行一次转化,对每个点来说,矩形框中心的位置必须在以当前点为中心的一个w,h的矩形框内,那么我们就可以把点转化为矩形,而把矩形转化为点。
之所以要进行这样的转化,是因为我们要移动矩形,而点是不动的,显然矩形这一模型比点要复杂,因此我们把静态的点转化为更复杂的矩形,而把动态的矩形转化为简单的点。
用一条扫描线的从左往右扫,维护沿y轴方向矩形数量的分布信息,注意对于转化后的问题,扫描线进入一个矩形以后,分布信息中就应在对应位置加上它,知道出这个矩形,删除对应信息。用线段树来维护当前沿y轴矩形数量分布信息。
实现会遇到一些小问题:
从左到右的距离太大——排序矩形的左右边,扫描矩形左右边。
纵向距离太大——离散化纵向座标。
按照题意点在框上的情况不算——由于输入都是整数,用一个小于0.5的小数修正即可。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define MXN 10010
int ll[MXN<<4],rr[MXN<<4],sum[MXN<<4],flag[MXN<<4];
int n,w,h;
int ans;
void build(int id,int l,int r){
ll[id]=l,rr[id]=r,sum[id]=flag[id]=0;
int m=(l+r)>>1,ls=id<<1,rs=ls|1;
if(l!=r){
build(ls,l,m);
build(rs,m+1,r);
}
}
struct line{
double x,l,h,v;
bool end;
line(){}
line(double a,double b,double c,long long e,bool d){x=a,l=b,h=c,end=d,v=e;}
bool operator < (const line& rgt)const{
return x<rgt.x||x==rgt.x&&end;
}
}l[MXN<<2];
long long lcnt,tot;
double dy[MXN<<2];
void input(){
ans=lcnt=tot=0;
for(int i=0;i<n;++i){
int tx,ty,tc;
scanf("%d%d%d",&tx,&ty,&tc);
double tl=ty-h/2.0+0.1;
double th=ty+h/2.0-0.1;
double ttx=tx-w/2.0+0.1;
l[lcnt++]=line(ttx,tl,th,tc,false);
ttx=tx+w/2.0-0.1;
l[lcnt++]=line(ttx,tl,th,tc,true);
dy[tot++]=tl;
dy[tot++]=th;
}
sort(l,l+lcnt);
sort(dy,dy+tot);
tot=unique(dy,dy+tot)-dy;
}
void down(int id);
void add(int id,double l,double r,int v,bool end){
if(flag[id]) down(id);
if(l==dy[ll[id]]&&r==dy[rr[id]]){
flag[id]+=end ? -v : v;
sum[id]+=flag[id];
return;
}
int m=(ll[id]+rr[id])>>1,ls=id<<1,rs=ls|1;
if(r<=dy[m]) add(ls,l,r,v,end);
else if(l>dy[m]) add(rs,l,r,v,end);
else{
add(ls,l,dy[m],v,end);
add(rs,dy[m+1],r,v,end);
}
sum[id]=max(sum[ls],sum[rs]);
}
void down(int id){
if(ll[id]==rr[id]){
flag[id]=0;
return;
}
int m=(ll[id]+rr[id])>>1,ls=id<<1,rs=ls|1;
add(ls,dy[ll[id]],dy[m],abs(flag[id]),flag[id]<0);
add(rs,dy[m+1],dy[rr[id]],abs(flag[id]),flag[id]<0);
flag[id]=0;
}
int query(int id){
if(flag[id]){
down(id);
}
return sum[id];
}
void solve(){
for(int i=0;i<lcnt;++i){
add(1,l[i].l,l[i].h,l[i].v,l[i].end);
ans=max(query(1),ans);
}
}
int main(){
//freopen("data.txt","r",stdin);
//freopen("ans.txt","w",stdout);
while(scanf("%d%d%d",&n,&w,&h)!=EOF){
input();
build(1,0,tot-1);
solve();
printf("%d\n",ans);
}
return 0;
}