题意:给你10000以内的星星的坐标和星星的亮度(即分别为x,y,c),要求用W*H的矩形去围住一个区域,使得这个区域内的星星的亮度最大,并且要求矩形边框上的星星不计入内。矩形可以平移,但不能旋转。
思路:
对x轴维护一个队列,使得任意两个点的x轴的距离小于W
对于y轴,把每个点拆分成y和y+H,[y,INF]加上c,[y+H,INF]加上-c
维护一个前缀的最大值
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int N=1e5;
struct Point{
long long x,y;
int c;
}a[N];
long long y[N];
int addv[N],maxv[N];
bool cmp(Point u,Point v){
if(u.x!=v.x)
return u.x<v.x;
return u.y<v.y;
}
int L,R,num;
void pushup(int rt){
maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]);
}
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
void pushdown(int rt){
if(addv[rt]){
maxv[rt<<1]+=addv[rt];
maxv[rt<<1|1]+=addv[rt];
addv[rt<<1]+=addv[rt];
addv[rt<<1|1]+=addv[rt];
addv[rt]=0;
}
}
void update(int l,int r,int rt){
if(L<=l&&R>=r){
addv[rt]+=num;
maxv[rt]+=num;
return ;
}
pushdown(rt);
int m=l+r>>1;
if(L<=m) update(lson);
if(R>m) update(rson);
pushup(rt);
}
int main(){
int n,W,H;
while(scanf("%d%d%d",&n,&W,&H)!=EOF){
int tot_x=0,tot_y=0,tot=0;
for(int i=1;i<=n;++i){
scanf("%lld%lld%d",&a[i].x,&a[i].y,&a[i].c);
y[++tot_y]=a[i].y,y[++tot_y]=a[i].y+H;
}
sort(a+1,a+n+1,cmp);
sort(y+1,y+tot_y+1);
tot_y=unique(y+1,y+tot_y+1)-y-1;
memset(addv,0,sizeof(addv));
memset(maxv,0,sizeof(maxv));
int ans=0,st=1;
for(int i=1;i<=n;++i){
ans=max(ans,maxv[1]);
while(st<i&&a[i].x-a[st].x>=W){
int l=lower_bound(y+1,y+tot_y+1,a[st].y)-y,r=lower_bound(y+1,y+tot_y+1,a[st].y+H)-y;
L=l,R=tot_y,num=-a[st].c;
update(1,tot_y,1);
L=r,R=tot_y,num=a[st].c;
update(1,tot_y,1);
++st;
}
int l=lower_bound(y+1,y+tot_y+1,a[i].y)-y,r=lower_bound(y+1,y+tot_y+1,a[i].y+H)-y;
L=l,R=tot_y,num=a[i].c;
update(1,tot_y,1);
L=r,R=tot_y,num=-a[i].c;
update(1,tot_y,1);
//printf("PPPPPP\n");
}
ans=max(ans,maxv[1]);
printf("%d\n",ans);
}
return 0;
}
思路二:如果c可能为负数,对于每一个星星,分别建立线(x,y,y+H,c)和(x+W,y,y+H,-c)。这样处理的原因是我们就可以把问题转化成求线段树里某一段内的最大值,即区间查询。矩形边框上的星星不计的处理方法是:1.对于x轴方面的处理是在排序的时候,优先-c的边,因为如果优先+c的边,那么就是将边框上的星星计入了。2.对于y轴方面的,我的处理方法是将线段树的叶子结点处理成长度为1的区间(转自http://blog.youkuaiyun.com/shiqi_614/article/details/7819232)
例如数据:
4 4 3
0 1 -100
0 2 -100
1 2 1
3 0 1
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int N=1e5;
struct Point{
long long x,y1,y2;
int c;
}a[N*2];
long long y[N];
int addv[N],maxv[N];
bool cmp(const Point& u,const Point& v){
if(u.x!=v.x)
return u.x<v.x;
return u.c<v.c;
}
int L,R,num;
void pushup(int rt){
maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]);
}
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
void pushdown(int rt){
if(addv[rt]){
maxv[rt<<1]+=addv[rt];
maxv[rt<<1|1]+=addv[rt];
addv[rt<<1]+=addv[rt];
addv[rt<<1|1]+=addv[rt];
addv[rt]=0;
}
}
void update(int l,int r,int rt){
if(L<=l&&R>=r){
addv[rt]+=num;
maxv[rt]+=num;
return ;
}
pushdown(rt);
int m=l+r>>1;
if(L<=m) update(lson);
if(R>m) update(rson);
pushup(rt);
}
int main(){
int n,W,H;
while(scanf("%d%d%d",&n,&W,&H)!=EOF){
int tot_y=0,tot=0,c;
long long x,y1;
for(int i=1;i<=n;++i){
scanf("%lld%lld%d",&x,&y1,&c);
a[i*2-1]=(Point){x,y1,y1+H-1,c};
a[i*2]=(Point){x+W,y1,y1+H-1,-c};
y[++tot_y]=y1,y[++tot_y]=y1+H-1;
}
sort(a+1,a+2*n+1,cmp);
sort(y+1,y+tot_y+1);
tot_y=unique(y+1,y+tot_y+1)-y-1;
memset(addv,0,sizeof(addv));
memset(maxv,0,sizeof(maxv));
int ans=-100000000,st=1;
for(int i=1;i<=2*n;i++){
L=lower_bound(y+1,y+tot_y+1,a[i].y1)-y,R=lower_bound(y+1,y+tot_y+1,a[i].y2)-y;
num=a[i].c;
update(1,tot_y,1);
ans=max(ans,maxv[1]);
}
printf("%d\n",ans);
}
return 0;
}