P9478 [NOI2023] 方格染色题解
题解
对于行操作,列操作和对角线操作,实际上仅仅只是在对若干个矩形求面积并而已,这是裸的扫描线题,套用模板即可,此时注意到对角线操作实际上是
显然,面积并具有交换性,我们先做
在做完
显然,这是
但是我们仍然有可能多统计,具体有两方面,第一个,对角线之间可能重叠,我们可以在一开始就对对角线进行一次面积并,但我们仍然不需要线段树,由于本题对角线同向,两条线相交前提是两条线共线,只要截距相同,然后变成了可以
正确性和效率都得到了保证,可以开始码了,这里使用了动态开点的线段树,省去离散化的过程了。
AC code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e6+10;
int c,n,m,q,T,X1,Y1,X2,Y2,tot,len,cnt,sz,rt;
int ans,flag[N];
map<pair<int,int>,int>Map;
struct scan {
int x,up,down,ty;
}L[N];
bool cmp(scan a,scan b) {
return a.x<b.x;
}
struct Line {
int X1,Y1,X2,Y2;
}L12[N],L3[N];
bool check1(Line a,Line b) {
if(a.X1-a.Y1!=b.X1-b.Y1) return false;
if(a.X2<b.X1||a.X1>b.X2) return false;
return true;
}
bool check2(Line a,Line b,int op) {
if(op==1) {
int X=b.X1-b.Y1+a.Y1;
if(Map[make_pair(X,a.Y1)]) return false;
if(a.X1<=X&&X<=a.X2&&b.X1<=X&&X<=b.X2) {
Map[make_pair(X,a.Y1)]=1;
return true;
}
return false;
}
else {
int Y=b.Y1-b.X1+a.X1;
if(Map[make_pair(a.X1,Y)]) return false;
if(a.Y1<=Y&&Y<=a.Y2&&b.Y1<=Y&&Y<=b.Y2) {
Map[make_pair(a.X1,Y)]=1;
return true;
}
return false;
}
}
struct node {
int ls,rs,len,cov;
}t[N<<2];
void pushup(int p,int L,int R) {
if(t[p].cov) t[p].len=R-L+1;
else t[p].len=t[t[p].ls].len+t[t[p].rs].len;
}
void update(int &p,int L,int R,int l,int r,int d) {
if(!p) p=++sz;
if(l<=L&&R<=r) {
t[p].cov+=d;
pushup(p,L,R);
return;
}
int mid=L+R>>1;
if(l<=mid) update(t[p].ls,L,mid,l,r,d);
if(r>mid) update(t[p].rs,mid+1,R,l,r,d);
pushup(p,L,R);
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>c>>n>>m>>q;
for(int i=1;i<=q;i++) {
cin>>T>>X1>>Y1>>X2>>Y2;
if(T==1||T==2) {
L[++tot].x=X1,L[tot].up=Y2,L[tot].down=Y1,L[tot].ty=1;
L[++tot].x=X2+1,L[tot].up=Y2,L[tot].down=Y1,L[tot].ty=-1;
L12[++cnt].X1=X1,L12[cnt].Y1=Y1,L12[cnt].X2=X2,L12[cnt].Y2=Y2;
}
if(T==3) L3[++len].X1=X1,L3[len].Y1=Y1,L3[len].X2=X2,L3[len].Y2=Y2;
}
sort(L+1,L+tot+1,cmp);
for(int i=1;i<tot;i++) {
update(rt,1,m,L[i].down,L[i].up,L[i].ty);
ans+=t[rt].len*(L[i+1].x-L[i].x);
}
for(int i=1;i<len;i++) {
if(!flag[i]) {
for(int j=i+1;j<=len;j++) {
if(!flag[j]&&check1(L3[i],L3[j])) {
L3[i].X1=min(L3[i].X1,L3[j].X1);
L3[i].Y1=min(L3[i].Y1,L3[j].Y1);
L3[i].X2=max(L3[i].X2,L3[j].X2);
L3[i].Y2=max(L3[i].Y2,L3[j].Y2);
flag[j]=1;
}
}
}
}
for(int i=1;i<=len;i++) {
if(flag[i]) continue;
ans+=L3[i].X2-L3[i].X1+1;
for(int j=1;j<=cnt;j++) {
if(L12[j].Y1==L12[j].Y2) {
if(check2(L12[j],L3[i],1)) ans--;
}
if(L12[j].X1==L12[j].X2){
if(check2(L12[j],L3[i],2)) ans--;
}
}
}
cout<<ans;
return 0;
}
本文作者:2021hych
本文链接:https://www.cnblogs.com/2021hych/p/18012498
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步