zsyzlzy

导航

 

我们先把题意转化一下,用whw*h的矩形框(不能取边界)等价于用(w1)(h1)(w-1)*(h-1)的矩形框(能取边界).
为什么?
因为合法星星集合中两两星星水平方向上的距离是不能大于w的,那么我们就证明为什么能把差为(w-1)的框进去.
如图:
在这里插入图片描述
我们把矩形的顶点挪到方格中心就行了嘛.h类似.

(之后的说法都按变化后的题意来,并且默认w和h都减了1)

因为矩形长宽固定,所以只要确定一个点的位置和点与点之间的相对位置,我们就能唯一确定它.
(讲得不清不楚 ).举个例子,只要确定右上角顶点,就能确定矩形.
所以我们可以考虑吧矩形的右上角放在哪个位置,框住星星的亮度总和最大.

能把一个坐标为(x,y)(x,y)的星星框住的矩形的右上角坐标(x1,y1)(x_1,y_1)必须满足
x1[x,x+w],y1[y,y+h]x_1\in [x,x+w] ,y_1\in[y,y+h].
我们假想出1个框,表示能把一个星星包住的右上角合法位置(框的边界也算)
如图:

再次提醒:w,hw,h默认已减1

多个点的话会出现下面的情况:

在这里插入图片描述
重叠部分表示矩形的右上角在那儿时,可把多个星星包住.
此时,我们可以把问题转化为:平面有多个区域,每个区域有一个权值(重叠部分权值累加),求最大权值

(一点扫描线的痕迹都没有)
我们假设有一条扫描线从左往右扫过,那么每个假设的框的左边就为入边,右边为出边.
我们把yy坐标离散化一下,再把边按xx排序一下,就可以做了.
假设的框的边界是可取的,所以点就不必转成段了.
线段树维护的是区间最大值.要用到延迟操作.
排序有点小细节,需要仔细理解.

说得不清不楚,所以重点看代码.

#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;
}
	
posted on 2019-07-23 20:50  zsyzlzy  阅读(118)  评论(0编辑  收藏  举报