LGP12699 [KOI 2022 R2] 红蓝 学习笔记

LGP12699 [KOI 2022 R2] 红蓝 学习笔记

Luogu Link

前言

一句话题解:窗外的星星·改。

题意简述

又是一个 \(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;
}
posted @ 2025-07-22 09:35  矞龙OrinLoong  阅读(198)  评论(0)    收藏  举报