题目地址


基本思想:

  • 扫描线

注意点:

  • 线段树建树时开大一点没坏处. 

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define int long long 
#define ll long long
using namespace std;
const int MAXN=8e6,root=1;
struct Node{
	int l,r;
	ll lazy,maxx;
	void reset(){
		l=r=lazy=maxx=0;
	}
}tr[MAXN];
void build(int p,int l,int r){
	tr[p].reset();
	tr[p].l=l,tr[p].r=r;
	if(l==r)return;
	int mid=(l+r)>>1;
	if(l<=mid)build(p<<1,l,mid);
	if(r>mid)build((p<<1)|1,mid+1,r);
}
void change(int p,int l,int r,int val){
	if(tr[p].l>=l&&tr[p].r<=r){
		tr[p].lazy+=val;
		tr[p].maxx+=val;
		return;
	}
	if(tr[p].lazy){
		tr[p<<1].lazy+=tr[p].lazy;
		tr[p<<1].maxx+=tr[p].lazy;
		tr[(p<<1)|1].lazy+=tr[p].lazy;
		tr[(p<<1)|1].maxx+=tr[p].lazy;
		tr[p].lazy=0;
	}
	int mid=(tr[p].l+tr[p].r)>>1;
	if(l<=mid)change(p<<1,l,r,val);
	if(r>mid)change((p<<1)|1,l,r,val);
	tr[p].maxx=max(tr[p<<1].maxx,tr[(p<<1)|1].maxx);
}
struct Star{
	ll x;//横轴坐标 
	int l,r;//y1 y2位置 
	ll c;//亮度 
	bool operator <(Star another)const{
		return x==another.x?c<another.c:x<another.x;
	}
}stars[MAXN];
ll b[MAXN],yCnt=0;//y坐标离散化 
void init(){
	memset(b,0,sizeof(b));
	yCnt=0;
}
signed main(){
	int t;
	scanf("%d",&t);
	ll n,w,h;
	while(cin>>n>>w>>h){
		init();
		for(int i=1;i<=n;i++){
			ll x,y,c;
			scanf("%lld%lld%lld",&x,&y,&c);
			stars[i].x=x,stars[i+n].x=x+w;
			stars[i].l=stars[i+n].l=y;
			stars[i].r=stars[i+n].r=y+h-1;
			stars[i].c=c,stars[i+n].c=-c;
			b[++yCnt]=y,b[++yCnt]=y+h-1;
		}
		//离散化
		sort(b+1,b+yCnt+1);
		int bCnt=unique(b+1,b+yCnt+1)-(b+1);//去重
		n=2*n;
		for(int i=1;i<=n;i++){
			stars[i].l=lower_bound(b+1,b+yCnt+1,stars[i].l)-b;
			stars[i].r=lower_bound(b+1,b+yCnt+1,stars[i].r)-b;
		} 
		sort(stars+1,stars+n+1);
		build(root,1,bCnt*2);
		ll ans=0;
		for(int i=1;i<=n;i++){
			change(root,stars[i].l,stars[i].r,stars[i].c);
			ans=max(ans,tr[root].maxx);
		}
		printf("%lld\n",ans);
	}
	return 0;
}