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;
}
posted @ 2023-08-14 16:30  Zimo_666  阅读(28)  评论(0编辑  收藏  举报