题目链接:https://www.luogu.org/problem/P1502
扫描线的板子题,把每个点看成矩形,存下边(x,y,y+h-1,li)和(x+w-1,y,y+h-1),在按横坐标扫线段更新y区间,线段树维护区间最大值
#include<iostream> #include<algorithm> using namespace std; #define ll long long #define ls l,mid,rt<<1 #define rs mid+1,r,rt<<1|1 #define maxn 20005 struct seg{ ll x,l,r,s,val; seg(){} seg(ll x,ll l,ll r,ll s,ll val):x(x),l(l),r(r),s(s),val(val){}; bool operator <(const seg &w)const{ if(x==w.x)return s>w.s; return x<w.x; } }se[maxn<<1]; struct node{ ll x,y,val,x1,y1; }a[maxn<<1]; ll n,w,h,ly[maxn<<1],ny; ll sum[maxn<<2],lazy[maxn<<2]; void pushup(int rt) { sum[rt]=max(sum[rt<<1],sum[rt<<1|1]); } void build(int l,int r,int rt) { sum[rt]=lazy[rt]=0; if(l==r) { return ; } int mid=l+r>>1; build(ls);build(rs); pushup(rt); } void pushdown(int rt) { if(lazy[rt]) { sum[rt<<1]+=lazy[rt]; sum[rt<<1|1]+=lazy[rt]; lazy[rt<<1]+=lazy[rt]; lazy[rt<<1|1]+=lazy[rt]; lazy[rt]=0; } } void update(int L,int R,int val,int l,int r,int rt) { if(L<=l&&R>=r) { sum[rt]+=val; lazy[rt]+=val; return ; } pushdown(rt); int mid=l+r>>1; if(L<=mid)update(L,R,val,ls); if(R>mid)update(L,R,val,rs); pushup(rt); } int main() { int t; cin>>t; while(t--) { cin>>n>>w>>h; int cnt=0; for(int i=1;i<=n;i++) { cin>>a[i].x>>a[i].y>>a[i].val; a[i].y1=a[i].y+h-1; ly[++cnt]=a[i].y;ly[++cnt]=a[i].y+h-1; se[cnt-1]=seg(a[i].x,a[i].y,a[i].y1,1,a[i].val); se[cnt]=seg(a[i].x+w-1,a[i].y,a[i].y1,-1,a[i].val); } sort(ly+1,ly+1+cnt); sort(se+1,se+1+cnt); ny=unique(ly+1,ly+1+cnt)-ly-1; build(1,ny,1); int l,r; ll ans=0; for(int i=1;i<=cnt;i++) { l=lower_bound(ly+1,ly+1+ny,se[i].l)-ly; r=lower_bound(ly+1,ly+1+ny,se[i].r)-ly; if(se[i].s==1)update(l,r,se[i].val,1,ny,1); else update(l,r,-se[i].val,1,ny,1); ans=max(ans,sum[1]); } cout<<ans<<endl; } return 0; }