LGP12699 [KOI 2022 R2] 红蓝 学习笔记
LGP12699 [KOI 2022 R2] 红蓝 学习笔记
前言
一句话题解:窗外的星星·改。
题意简述
又是一个 \(W\times H\) 的窗口,但是边框计入答案且窗口顶点坐标必为整数。有 \(n\) 个红点 \(m\) 个蓝点。红点有正一权值,蓝点有负一权值,最大化选择窗口内的权值的绝对值,并输出矩形左下角的坐标(若有多个,任意输出一个)。
\(n+m\le 2\times 10^5\)。坐标在 \(10^9\) 范围内且非负。
做法解析
糖点解析:一开始题读错了。
看完题意简述你也可以意识到这就是“窗外的星星·改”了。所以题解略。
哦因为要输出方案所以再讲一嘴。结点同时维护其mx值与mn值的下标来源。
附传送门:mLGP1502。
代码实现
#include <bits/stdc++.h>
using namespace std;
using namespace obasic;
const int MaxN=1e5+5;
int N,M,W,H,X[MaxN<<1],Y[MaxN<<1];
int Xs[MaxN<<2],xcnt,Ys[MaxN<<2],ycnt;
struct anob{int l,r,c;};
vector<anob> S[MaxN<<2];
struct bnob{int k,x,y;}ans;
struct SegTree{
struct adat{
int k,p;
friend adat& operator+=(adat &a,int x){a.k+=x;return a;}
friend bool operator<(adat a,adat b){return a.k<b.k;}
}mx[MaxN<<4],mn[MaxN<<4];
int tag[MaxN<<4];
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)]),mn[u]=min(mn[ls(u)],mn[rs(u)]);}
void build(int u,int cl,int cr){
if(cl==cr){mx[u]={0,cl},mn[u]={0,cl};return;}int cmid=(cl+cr)>>1;
build(ls(u),cl,cmid),build(rs(u),cmid+1,cr),pushup(u);
}
void maketag(int u,int x){mx[u]+=x,mn[u]+=x,tag[u]+=x;}
void pushdown(int u){if(tag[u])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);
}
}SgT;
int main(){
readis(N,M,W,H);
for(int i=1;i<=N;i++)readis(X[i],Y[i]);
for(int i=1;i<=M;i++)readis(X[i+N],Y[i+N]);
for(int i=1;i<=N+M;i++)Xs[i]=X[i]-W,Ys[i]=Y[i]-H;
for(int i=1;i<=N+M;i++)Xs[i+N+M]=X[i],Ys[i+N+M]=Y[i]+1;
sort(Xs+1,Xs+(N+M)*2+1);xcnt=unique(Xs+1,Xs+(N+M)*2+1)-(Xs+1);
sort(Ys+1,Ys+(N+M)*2+1);ycnt=unique(Ys+1,Ys+(N+M)*2+1)-(Ys+1);
for(int i=1,lx,rx,ly,ry,cc;i<=N+M;i++){
lx=lwberi(Xs,xcnt,X[i]-W),rx=lwberi(Xs,xcnt,X[i]);
ly=lwberi(Ys,ycnt,Y[i]-H),ry=lwberi(Ys,ycnt,Y[i]+1);
cc=(i<=N?1:-1);S[ly].push_back({lx,rx,cc}),S[ry].push_back({lx,rx,-cc});
}
SgT.build(1,1,xcnt);
for(int i=1;i<=ycnt;i++){
for(auto [l,r,c] : S[i])SgT.update(1,1,xcnt,l,r,c);
auto [mxk,mxp]=SgT.mx[1];auto [mnk,mnp]=SgT.mn[1];
if(mxk>ans.k)ans={mxk,mxp,i};
if(-mnk>ans.k)ans={-mnk,mnp,i};
}
writil(ans.k);
printf("%d %d",Xs[ans.x],Ys[ans.y]);
return 0;
}
浙公网安备 33010602011771号