LGP9478 [NOI 2023] 方格染色 学习笔记
LGP9478 [NOI 2023] 方格染色 学习笔记
前言
2023:
\(\texttt{NOI}\) 为什么会出这么简单的题目。不过我省队都进不了,管这些干什么。——\(\text{Purslane}\)
2024:
没想到 \(\texttt{NOI2024 d1t1}\) 更加弱智,打 \(\texttt{OI}\) 的这辈子有了。
2025:
(你知道这年的签到是个什么东西)
(另外 \(\text{Purslane}\) 金了)
笑点解析:
- 这题在洛谷上被降蓝了。
- 截止 \(\texttt{20250724}\),\(\text{OrinLoong}\) 做完了三年的国赛签到,然而他连七级钩都没有。
- 上面的截止日期本来是二十三号,但因为这题调起来太史导致二十三号没调完。
题意简述
\(n\times m\) 的棋盘格。记第 \(i\) 列,第 \(j\) 行的方格坐标记为 \((i,j)\)。
三种操作。染一条横线、染一条竖线、染一条斜率为 \(1\) 的斜线。最多染 \(5\) 次斜线。
问最终有多少个格子被染。
\(n,m\le 10^9\),\(q\le 10^5\)。
做法解析
没有斜线时显然是矩形面积并模板,不会的出门左转这里。不过这两题的代码还是有一些区别,因为这题给的都是格子的坐标。为了简单处理这一点,我们给所有直线(即矩形)那个较大的 \(x_i\) 和 \(y_i\) 加 \(1\)。
如果坐标值域没到 \(10^9\) ,斜线可以暴力拆成一个一个 \(1\times 1\) 方格参与矩形面积并计算(这足够你获得 \(\text{95pts}\))。但坐标值域到了 \(10^9\) 怎么办呢?考虑先把斜线面积全算上再去重。为了防止一个斜线和多条直线相交于同一点而被去重多次,可以开个map来防止多次去重。
代码实现
代码里那个sort(Xs+1,Xs+scnt+1)是因为这里离散化前的x坐标数量确实就等于scnt。
如果一遍没写对调起来会挺折磨。给这题降蓝的多少有点 \(\texttt{starbeat}\)。
#include <bits/stdc++.h>
using namespace std;
using namespace obasic;
const int MaxQ=1e5+5;
int Tpn,N,M,Q,Opt,X1,Y1,X2,Y2,scnt;
int Xs[MaxQ<<1],xcnt;
struct oper{int o,lx,ly,rx,ry;}P[MaxQ];
struct anob{int lx,rx,y,w;}S[MaxQ<<1];
bool cmpy(anob a,anob b){return a.y<b.y;}
struct SegTree{
int cov[MaxQ<<3],flen[MaxQ<<3];
int ls(int u){return u<<1;}
int rs(int u){return (u<<1)|1;}
void pushup(int u,int cl,int cr){
if(cov[u]){flen[u]=Xs[cr+1]-Xs[cl];return;}
flen[u]=(cl==cr?0:flen[ls(u)]+flen[rs(u)]);
}
void update(int u,int cl,int cr,int dl,int dr,int x){
if(dl<=cl&&cr<=dr){cov[u]+=x,pushup(u,cl,cr);return;}
int cmid=(cl+cr)>>1;
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,cl,cr);
}
}SgT;
lolo ans;int tcnt,flg[6];
struct bnob{int lx,rx,ly;}T[6];
void tcomb(){
for(int i=1;i<=tcnt;i++)flg[i]=1;
for(int i=1;i<=tcnt;i++){
if(!flg[i])continue;
for(int j=i+1;j<=tcnt;j++){
if(!flg[j])continue;
if(T[i].ly-T[i].lx!=T[j].ly-T[j].lx)continue;
if(T[i].rx<=T[j].lx||T[j].rx<=T[i].lx)continue;
minner(T[i].lx,T[j].lx),maxxer(T[i].rx,T[j].rx),minner(T[i].ly,T[j].ly),flg[j]=0;
}
}
}
int main(){
readi(Tpn);readis(N,M,Q);
for(int i=1;i<=Q;i++){
readis(Opt,X1,Y1,X2,Y2),X2++,Y2++;
P[i]={Opt,X1,Y1,X2,Y2};
Xs[(i<<1)-1]=X1,Xs[i<<1]=X2;
if(Opt==3)T[++tcnt]={X1,X2,Y1};
else S[++scnt]={X1,X2,Y1,1},S[++scnt]={X1,X2,Y2,-1};
}
sort(S+1,S+scnt+1,cmpy);
sort(Xs+1,Xs+(Q<<1)+1),xcnt=unique(Xs+1,Xs+(Q<<1)+1)-(Xs+1);
for(int i=1;i<=scnt;i++)S[i].lx=lwberi(Xs,xcnt,S[i].lx),S[i].rx=lwberi(Xs,xcnt,S[i].rx)-1;
for(int i=1;i<scnt;i++){
auto [lx,rx,y,w]=S[i];
SgT.update(1,1,xcnt-1,lx,rx,w);
ans+=1ll*SgT.flen[1]*(S[i+1].y-S[i].y);
}
tcomb();map<pii,bool> mp;
for(int i=1;i<=tcnt;i++)if(flg[i])ans+=T[i].rx-T[i].lx;
for(int j=1;j<=tcnt;j++){
if(!flg[j])continue;
auto [jlx,jrx,jly]=T[j];
int jry=jly+(jrx-jlx);
for(int i=1;i<=Q;i++){
auto &[co,clx,cly,crx,cry]=P[i];
if(co==1){
if(cry<=jly||jry<=cly)continue;
int jtx=jlx+(cly-jly);if(jtx>=crx||jtx<clx)continue;
pii cp={jtx,cly};if(!mp[cp])mp[cp]=1,ans--;
}
if(co==2){
if(crx<=jlx||jrx<=clx)continue;
int jty=jly+(clx-jlx);if(jty>=cry||jty<cly)continue;
pii cp={clx,jty};if(!mp[cp])mp[cp]=1,ans--;
}
}
}
writil(ans);
return 0;
}
浙公网安备 33010602011771号