题目链接:https://www.luogu.org/problem/P1502
其实一眼看不出扫描线。
我们可以把每一个点都变成一个长宽为w和h的矩形。
左边的边是+w,右边的边是-w。
线段树维护区间max和lazy tag。
然后扫描线求max。
代码如下:
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=20010; int n,w,h,t,b[maxn<<1],tot; struct node{ ll mx,tag; #define mx(x) tree[x].mx #define tag(x) tree[x].tag }tree[maxn<<2]; struct s{ int x,yl,yh,fl; s(){} s(int xx,int yy1,int yy2,int ff){x=xx;yl=yy1;yh=yy2;fl=ff;} }e[maxn<<1]; inline bool cmp(s x,s y){ return x.x==y.x ? x.fl>y.fl : x.x<y.x; } inline void pushdown(int p,int l,int r){ if(!tag(p)) return; mx(p)+=tag(p); if(l!=r){ tag(p<<1)+=tag(p); tag(p<<1|1)+=tag(p); } tag(p)=0; } inline void add(int p,int l,int r,int x,int y,int d){ if(x<=l&&r<=y){ tag(p)+=d;return; } int mid=(l+r)>>1; if(x<=mid) add(p<<1,l,mid,x,y,d); if(y>mid) add(p<<1|1,mid+1,r,x,y,d); pushdown(p<<1,l,mid); pushdown(p<<1|1,mid+1,r); mx(p)=max(mx(p<<1),mx(p<<1|1)); } int main() { scanf("%d",&t); while(t--){ memset(tree,0,sizeof(tree)); tot=0; scanf("%d%d%d",&n,&w,&h); for(int i=1;i<=n;i++){ int x,y,v; scanf("%d%d%d",&x,&y,&v); e[++tot].x=x;b[tot]=y; e[tot].yl=y;e[tot].yh=y+h-1;e[tot].fl=v; e[++tot].x=x+w-1;b[tot]=y+h-1; e[tot].yl=y;e[tot].yh=y+h-1;e[tot].fl=-v; } sort(b+1,b+1+2*n); tot=unique(b+1,b+1+2*n)-b-1; sort(e+1,e+1+2*n,cmp); ll ans=0; for(int i=1;i<=2*n;i++){ int h1=lower_bound(b+1,b+1+tot,e[i].yh)-b; int h2=lower_bound(b+1,b+1+tot,e[i].yl)-b; e[i].yl=h2;e[i].yh=h1; } for(int i=1;i<=2*n;i++){ add(1,1,2*n,e[i].yl,e[i].yh,e[i].fl); ans=max(ans,mx(1)); } printf("%lld\n",ans); } return 0; }