P1502 窗口的星星
P1502 窗口的星星
题意
在一个二维坐标系下,有一些点,每个点有一个权值。我们有一个长宽为 \((H,W)\) 的矩形,求放置在什么位置可以使得点权最大。
分析
我们考虑把每个点作为一个矩形的左下角,以该点建立长宽为 \((H,W)\) 的矩形,每个点权值都为 \(val\) 来代替那颗星星,那么求算所有矩形覆盖起来权值最大值。
我们考虑 扫描线
的做法。我们考虑先把所有点的横坐标离散化,考虑扫描线从下往上扫时对于每个矩形来说对答案的贡献。
对于每个矩形,扫到下边时把 \([L,R] +val\),扫到上边时 \([L,R] -val\),这样能够保证在这个矩形内贡献的继承性。
记得把每条关键边丢进一个 vector
里然后排序。
设离散化后值域为 \([1,m]\),则每次查询 \([1,m]\) 最大值即可。操作用线段树实现,需要区间修改,区间查询最大值。
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define mid ((l+r)>>1)
#define ls (k<<1)
#define rs (k<<1|1)
const int N=1e6+7;
int T;
int n,w,h;
struct node{
int l,r,y,val;
node(int L=0,int R=0,int Y=0,int V=0){
l=L,r=R,y=Y,val=V;
}
};
struct seg_tree{
int maxx[N<<2],tag[N<<2];
void init(){
memset(maxx,0,sizeof maxx);memset(tag,-1,sizeof tag);
}
void pushup(int k,int l,int r){maxx[k]=max(maxx[ls],maxx[rs]);}
void add(int k,int l,int r,int val){
maxx[k]+=val;
tag[k]+=val;
}
void pushdown(int k,int l,int r){
if(tag[k]!=-1){
add(ls,l,mid,tag[k]),add(rs,mid+1,r,tag[k]);
tag[k]=-1;
}
}
// void build(int k,int l,int r){
// if(l==r) return maxx[k]=b[l],void();
// build(ls,l,mid),build(rs,mid+1,r);
// pushup(k,l,r);
// }
void modify(int k,int l,int r,int x,int y,int val){
if(x<=l&&y>=r) return maxx[k]+=val,tag[k]+=val,void();
// if(x>r||y<l) return;
pushdown(k,l,r);
if(x<=mid) modify(ls,l,mid,x,y,val);
if(y>=mid+1) modify(rs,mid+1,r,x,y,val);
pushup(k,l,r);
}
int query(int k,int l,int r,int x,int y){
// printf("%d %d %d %d %d\n",k,l,r,x,y);
if(x<=l&&y>=r) return maxx[k];
// if(x>r||y<l) return 0;
pushdown(k,l,r);
int res=0;
if(x<=mid) res=max(res,query(ls,l,mid,x,y));
if(y>=mid+1) res=max(res,query(rs,mid+1,r,x,y));
return res;
}
}TT;
void solve(){
scanf("%lld%lld%lld",&n,&w,&h);w--,h--;
vector<int> vec;vector<node> seg;
TT.init();
for(int i=1;i<=n;i++){
int x,y,val;scanf("%lld%lld%lld",&x,&y,&val);
vec.push_back(x),vec.push_back(x+w);
seg.emplace_back(x,x+w,y,val);seg.emplace_back(x,x+w,y+h,-val);
}
sort(vec.begin(),vec.end());
vec.erase(unique(vec.begin(),vec.end()),vec.end());
sort(seg.begin(), seg.end(), [&] (const node& A, const node& B) {
return A.y == B.y ? A.val > B.val : A.y < B.y;
});
int ans=0;
for(auto [l,r,y,val]:seg){
l=lower_bound(vec.begin(),vec.end(),l)-vec.begin()+1;
r=lower_bound(vec.begin(),vec.end(),r)-vec.begin()+1;
TT.modify(1,1,vec.size(),l,r,val),ans=max(ans,TT.query(1,1,vec.size(),l,r));
}
printf("%lld\n",ans);
}
signed main(){
cin>>T;
while(T--){solve();}
return 0;
}