LGP1502 窗口的星星 学习笔记

LGP1502 窗口的星星 学习笔记

Luogu Link

前言

晚上,小卡(指かすみ)从阳台望出去……

“我小时候,听见过「星星的声音」;”
“那闪闪发光,心跳加速的,我十分向往;”
“我也想キラキラ,ドキドキ!”

不过她还没给这个房间设一个窗户。

天真的小卡总是希望能够在晚上能看到最多最亮的星星,但是窗子的大小是固定的,边也必须和地面平行。

这时小卡被ありさ扣晕了过去,于神志不清中看到了墙后面每个星星的位置和亮度。但是小卡被扣晕后就很疲劳,只好拜托你告诉她最多能够有总和多亮的星星能出现在窗口上。

你要不看看你自己上文写的什么东西?

题意简述

前文之述备矣。

\(n\le 10^4\)。保证 \(x,y\) 都在int范围内且都非负。

做法解析

扫描线经典题。

这题最关键的转化是:问一个 \(W\times H\) 的不算边框的矩形可以盖住多少个点,等效于一个点最多可以覆盖上多少个 \((W-1)\times(H-1)\)(算边框)的矩形。

具体来说,规定向右为 \(x\) 方向,向上为 \(y\) 方向。我们考虑:确定原矩形一个角的坐标就相当于确定了矩形的位置。你发现因为边框不算,让顶点落在 \(x,y\) 坐标为整数的地方劣。那么,如果一个点 \((x_i,y_i)\) 能被右上角为 \((x_u+\epsilon,y_u+\epsilon)\),宽 \(W\)\(H\) 不计边框的矩形覆盖,那这个点的坐标范围如何呢?(当然,\(x_i,y_i\) 都是整数)答案是 \(x_u\in [x_i,x_i+W)\)\(y_u\in [y_i,y_i+H)\)。这样,问题得以转化。

然后就是扫描线了。这里不展开讲。

代码实现

线段树开八倍空间,因为有效的 \(x\) 坐标是 \(O(2n)\) 的。

为了防止被边角数据卡掉,开个uint

#include <bits/stdc++.h>
using namespace std;
using namespace obasic;
const int MaxN=1e4+5;
int N,W,H,ans,Z[MaxN];uint X[MaxN],Y[MaxN];
uint Xs[MaxN<<1],xcnt,Ys[MaxN<<1],ycnt;
struct anob{int l,r,c;};
vector<anob> S[MaxN<<1];
struct SegTree{
    int mx[MaxN<<3],tag[MaxN<<3];
    int ls(int u){return u<<1;}
    int rs(int u){return (u<<1)|1;}
    void pushup(int u){mx[u]=max(mx[ls(u)],mx[rs(u)]);}
    void maketag(int u,int x){mx[u]+=x,tag[u]+=x;}
    void pushdown(int u){
        if(!tag[u])return;
        maketag(ls(u),tag[u]),maketag(rs(u),tag[u]),tag[u]=0;
    }
    void update(int u,int cl,int cr,int dl,int dr,int x){
        if(dl<=cl&&cr<=dr){maketag(u,x);return;}
        int cmid=(cl+cr)>>1;pushdown(u);
        if(dl<=cmid)update(ls(u),cl,cmid,dl,dr,x);
        if(dr>cmid)update(rs(u),cmid+1,cr,dl,dr,x);
        pushup(u);return;
    }
}SgT;
void mian(){
    readis(N,W,H);ans=0;
    for(int i=1;i<=N;i++){
        readis(X[i],Y[i],Z[i]);
        Xs[(i<<1)+1]=X[i],Xs[(i<<1)+2]=X[i]+W-1;
        Ys[(i<<1)+1]=Y[i],Ys[(i<<1)+2]=Y[i]+H;
    }
    sort(Xs+1,Xs+N*2+1),xcnt=unique(Xs+1,Xs+N*2+1)-(Xs+1);
    sort(Ys+1,Ys+N*2+1),ycnt=unique(Ys+1,Ys+N*2+1)-(Ys+1);
    for(int i=1;i<=ycnt;i++)S[i].clear();
    for(int i=1,lx,rx,ly,ry;i<=N;i++){
        lx=lwberi(Xs,xcnt,X[i]),rx=lwberi(Xs,xcnt,X[i]+W-1);
        ly=lwberi(Ys,ycnt,Y[i]),ry=lwberi(Ys,ycnt,Y[i]+H);
        S[ly].push_back({lx,rx,Z[i]});
        S[ry].push_back({lx,rx,-Z[i]});
    }
    for(int i=1;i<=ycnt;i++){
        for(auto [l,r,c] : S[i])SgT.update(1,1,xcnt,l,r,c);
        maxxer(ans,SgT.mx[1]);
    }
    writil(ans);
}
int Tcn;
int main(){
    readi(Tcn);
    while(Tcn--)mian();
    return 0;
}
posted @ 2025-07-21 21:16  矞龙OrinLoong  阅读(6)  评论(0)    收藏  举报