我们先把题意转化一下,用
w
∗
h
w*h
w∗h的矩形框(不能取边界)等价于用
(
w
−
1
)
∗
(
h
−
1
)
(w-1)*(h-1)
(w−1)∗(h−1)的矩形框(能取边界).
为什么?
因为合法星星集合中两两星星水平方向上的距离是不能大于w的,那么我们就证明为什么能把差为(w-1)的框进去.
如图:
我们把矩形的顶点挪到方格中心就行了嘛.h类似.
(之后的说法都按变化后的题意来,并且默认w和h都减了1)
因为矩形长宽固定,所以只要确定一个点的位置和点与点之间的相对位置,我们就能唯一确定它.
(讲得不清不楚 ).举个例子,只要确定右上角顶点,就能确定矩形.
所以我们可以考虑吧矩形的右上角放在哪个位置,框住星星的亮度总和最大.
能把一个坐标为
(
x
,
y
)
(x,y)
(x,y)的星星框住的矩形的右上角坐标
(
x
1
,
y
1
)
(x_1,y_1)
(x1,y1)必须满足
x
1
∈
[
x
,
x
+
w
]
,
y
1
∈
[
y
,
y
+
h
]
x_1\in [x,x+w] ,y_1\in[y,y+h]
x1∈[x,x+w],y1∈[y,y+h].
我们假想出1个框,表示能把一个星星包住的右上角合法位置(框的边界也算)
如图:
再次提醒: w , h w,h w,h默认已减1
多个点的话会出现下面的情况:
重叠部分表示矩形的右上角在那儿时,可把多个星星包住.
此时,我们可以把问题转化为:平面有多个区域,每个区域有一个权值(重叠部分权值累加),求最大权值
(一点扫描线的痕迹都没有)
我们假设有一条扫描线从左往右扫过,那么每个假设的框的左边就为入边,右边为出边.
我们把
y
y
y坐标离散化一下,再把边按
x
x
x排序一下,就可以做了.
假设的框的边界是可取的,所以点就不必转成段了.
线段树维护的是区间最大值.要用到延迟操作.
排序有点小细节,需要仔细理解.
说得不清不楚,所以重点看代码.
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define g getchar()
#define lc (x<<1)
#define rc (x<<1|1)
using namespace std;
const int N=10010;
int n,w,h,m;
struct line {
int x,y,z,k;
bool operator <(line b) const {
return x!=b.x?x<b.x:k<b.k;
}
}a[N<<1];
int raw[N<<1];
void disc() {
sort(raw+1,raw+n+1); m=1;
for(int i=2;i<=n;i++)
if(raw[i]!=raw[m]) raw[++m]=raw[i];
}
int val(int x) {
int l=1,r=m,mid;
while(l<r) {
int mid=(l+r)>>1;
if(raw[mid]<x)l=mid+1;
else r=mid;
}
return l;
}
struct node {
int mx,ad;
}tr[N<<3];
void bt(int x,int l,int r) {
tr[x].mx=tr[x].ad=0;
if(l==r)return ;
int mid=(l+r)>>1;
bt(lc,l,mid);
bt(rc,mid+1,r);
}
int lazy(int x,int l,int r) {
int mid=(l+r)>>1;
if(tr[x].ad) {
tr[lc].ad+=tr[x].ad; tr[lc].mx+=tr[x].ad;
tr[rc].ad+=tr[x].ad; tr[rc].mx+=tr[x].ad;
tr[x].ad=0;
}
return mid;
}
void add(int x,int l,int r,int L,int R,int d) {
if(L<=l&&r<=R) {
tr[x].ad+=d;
tr[x].mx+=d;
return ;
}
int mid=lazy(x,l,r);
if(L<=mid) add(lc,l,mid,L,R,d);
if(mid< R) add(rc,mid+1,r,L,R,d);
tr[x].mx=max(tr[lc].mx,tr[rc].mx);
}
void qr(int &x) {
char c=g;x=0;int f=1;
while(!isdigit(c)){if(c=='-')f=-1; c=g;}
while(isdigit(c))x=x*10+c-'0',c=g;
x*=f;
}
int main() {
while(~scanf("%d%d%d",&n,&w,&h)) {
for(int i=1,j=2;i<=n;i++,j+=2) {
int x,y,c;qr(x);qr(y);qr(c);
a[j-1]=(line){x,y,y+h-1,c};
a[j ]=(line){x+w,y,y+h-1,-c};
raw[j-1]=y;raw[j]=y+h-1;
}
n<<=1; disc(); sort(a+1,a+n+1);
bt(1,1,m-1); int ans=0;
for(int i=1;i<=n;i++) {
int y=val(a[i].y),z=val(a[i].z)-1;
add(1,1,m-1,y,z,a[i].k);
ans=max(ans,tr[1].mx);
}
printf("%d\n",ans);
}
return 0;
}