LGP1502 窗口的星星 学习笔记
LGP1502 窗口的星星 学习笔记
前言
晚上,小卡(指かすみ)从阳台望出去……
“我小时候,听见过「星星的声音」;”
“那闪闪发光,心跳加速的,我十分向往;”
“我也想キラキラ,ドキドキ!”不过她还没给这个房间设一个窗户。
天真的小卡总是希望能够在晚上能看到最多最亮的星星,但是窗子的大小是固定的,边也必须和地面平行。
这时小卡被ありさ扣晕了过去,于神志不清中看到了墙后面每个星星的位置和亮度。但是小卡被扣晕后就很疲劳,只好拜托你告诉她最多能够有总和多亮的星星能出现在窗口上。
你要不看看你自己上文写的什么东西?
题意简述
前文之述备矣。
\(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;
}
浙公网安备 33010602011771号