传送门

提供一个神奇的思路。

首先二维数点能想到扫描线+线段树。

边框不能取,珂以把长、宽都减$1$,因为你可以这么框:

也就是说边界不取整数。

然后将坐标系上每个点扩展为一个矩形:

大概就是这种感觉:把每个点向左下角扩展得到它代表的矩形。

对于每颗星星,把它能影响到的矩形加上它的贡献。

不考虑横坐标,它能影响到的矩形为:$y$到$y+h$的点所代表的所有矩形。

考虑上横坐标,用扫描线,及时删除不在当前横坐标能覆盖的星星。

这样把每个可能的矩形缩成一个点,用线段树维护最大值,边扫边取最大值就行了。

时间复杂度:$O(t·nlogn)$

(说着轻快其实蒟蒻调了好长时间,边界的处理太麻烦了,具体细节还是看代码吧$QAQ$)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>

#define maxn 10005
#define inf 0x3f3f3f3f
#define pn putchar('\n')
#define px(x) putchar(x)
#define ps putchar(' ')
#define pd puts("======================")
#define pj puts("++++++++++++++++++++++")

using namespace std;

inline int read(){
    int x=0,y=0;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')y=1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return y?-x:x;
}
template<typename T>
inline T read(){
    T x=0;
    int y=0;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')y=1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return y?-x:x;
}
struct Segment_Tree{
    long long dat[maxn<<2],tag[maxn<<2];
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
    inline void update(int node){
        dat[node]=max(dat[ls(node)],dat[rs(node)]);
    }
    inline void datadown(int node,long long d){
        dat[node]+=d;
        tag[node]+=d;
    }
    inline void pushdown(int node){
        datadown(ls(node),tag[node]);
        datadown(rs(node),tag[node]);
        tag[node]=0;
    }
    void add(int L,int R,int l,int r,int node,long long d){
        if(L<=l&&R>=r){
            datadown(node,d);
            return;
        }
        if(tag[node])pushdown(node);
        int mid=l+r>>1;
        if(L<=mid)add(L,R,l,mid,ls(node),d);
        if(R>mid)add(L,R,mid+1,r,rs(node),d);
        update(node);
    }
    inline void clear(){
        memset(dat,0,sizeof dat);
        memset(tag,0,sizeof tag);
    }
}st;
int dis[maxn];
//离散化数组
struct POINT{
    int x,y,ll,rr;
    long long d;
}p[maxn];
//星星:x、y是坐标,ll、rr是它能覆盖的矩形范围,d是亮度
inline bool cmp(POINT x,POINT y){
    return x.x<y.x;
}
int main(){
    int t=read();
    while(t--){
        int n=read(),w=read()-1,h=read()-1,len=0,head=1;
        //长宽各-1
        for(register int i=1;i<=n;++i)
            p[i].x=read(),dis[++len]=p[i].y=read(),p[i].d=read<long long>();
        dis[++len]=(1ll<<31)-1;
        //加了一个无穷大的边界
        sort(dis+1,dis+1+len);
        sort(p+1,p+1+n,cmp);//把星星按横坐标排序
        len=unique(dis+1,dis+1+len)-dis-1;
        long long ans=0;
        for(register int i=1;i<=n;++i){
            p[i].ll=upper_bound(dis+1,dis+1+len,p[i].y)-dis,p[i].rr=upper_bound(dis+1,dis+1+len,p[i].y+h)-dis;
            //要用upper_bound,两边是可以等于的
            st.add(p[i].ll,p[i].rr,1,len,1,p[i].d);
            while(p[i].x-w>p[head].x)st.add(p[head].ll,p[head].rr,1,len,1,-p[head].d),++head;
            //通过head头指针删除点
            ans=max(ans,st.dat[1]);    
        }
        printf("%lld\n",ans);
        st.clear();
    }
}