题目大意: 有 n n n 个有权值的点,有一个 H × W H\times W H×W 的矩形,问这个矩形最多可以框住多少权值。
题解
当然不可能让这个矩形跑来跑去看看能框多少,所以,需要换一个思路。既然矩形找点不好找,那么可以把每个点转化成一个矩形,然后找被矩形们覆盖次数最多的点。这样来看,就是要用扫描线了。
做法很显然了,就直接上代码啦:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
int t,n,W,H;
struct point{int x,yd,yu,p;};
point dian[20010];
int yy[20010],tot,ynew[20010],tt;
int maxx(int x,int y){return x>y?x:y;}
struct node{
int l,r,ma,late;//late即是lazy标记
node *zuo,*you;
node():zuo(NULL),you(NULL),ma(0),late(0){}
void buildtree(int x,int y)
{
l=ynew[x],r=ynew[y];
if(x<y)
{
int mid=x+y>>1;
zuo=new node;zuo->buildtree(x,mid);
you=new node;you->buildtree(mid+1,y);
}
}
void push()
{
if(late!=0)
{
ma+=late;
if(zuo!=NULL)zuo->late+=late,you->late+=late;
late=0;
}
}
void change(int x,int y,int c)
{
push();
if(x==l&&r==y)
{
late+=c;
push();
return;
}
if(y<=zuo->r)zuo->change(x,y,c);
else if(x>=you->l)you->change(x,y,c);
else zuo->change(x,zuo->r,c),you->change(you->l,y,c);
zuo->push(),you->push();//注意一定要有这一步,结合上面代码就可以理解了
ma=maxx(zuo->ma,you->ma);
}
void del()
{
if(zuo!=NULL)zuo->del(),you->del();
delete this;
}
};
//注意排序的时候,横坐标相同的要先处理矩形的左边
bool cmp(point x,point y){return x.x<y.x||(x.x==y.x&&x.p>y.p);};
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d %d %d",&n,&W,&H);
W--;H--;//由于边界上的不算,所以将他们-1
tot=0;
for(int i=1;i<=n;i++)
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
dian[++tot]=(point){x,y,y+H,z};
yy[tot]=y;
dian[++tot]=(point){x+W,y,y+H,-z};
yy[tot]=y+H;
}
sort(dian+1,dian+tot+1,cmp);
sort(yy+1,yy+tot+1);
tt=0;
yy[0]=-233;
for(int i=1;i<=tot;i++)
if(yy[i]!=yy[i-1])ynew[++tt]=yy[i];//去一下重,否则会WA掉一个点(洛谷上)
node *root=new node;
root->buildtree(1,tt);
int ans=0;
for(int i=1;i<=tot;i++)
{
if(root->ma>ans)ans=root->ma;//对比最大值,更新答案
root->change(dian[i].yd,dian[i].yu,dian[i].p);
}
root->del();
printf("%d\n",ans);
}
}
/*
附赠一组数据:
1
6 3 5
1 1 1
2 1 5
3 4 7
5 5 8
6 4 4
7 8 4
8 * * * * * * 4 *
7 * * * * * * * *
6 * * * * * * * *
5 * * * * 8 * * *
4 * * 7 * * 4 * *
3 * * * * * * * *
2 * * * * * * * *
1 1 5 * * * * * *
0 1 2 3 4 5 6 7 8
ans=16
*/