P9478 [NOI2023] 方格染色
考虑特殊问题一般化。若只有行和列的操作,可以直接扫描线,计算矩形面积并。
斜方向的操作最多进行 \(5\) 次,所以每个操作可以拆成 \(O(n)\) 个小正方形参与面积并。
这样就能拿 \(95\) 了。
瓶颈在于斜方向有一个 \(O(n)\),所以考虑不拆成小正方形,而是先计算没有斜线的答案,再枚举每一条斜线。
对于枚举的斜线,我们可以 \(O(q)\) 地遍历行和列的操作,并求出于它重合的位置数量(注意使用 set 去重)。对答案的贡献即为斜线长度、再减去重合位置的数量。
时间复杂度 \(O(q\log q)\)。
实现细节上,需要注意两斜线若存在公共点,需要将它们合并成一条,否则会重复统计答案。
点击查看代码
#include<bits/stdc++.h>
#define eb emplace_back
#define PII pair<int,int>
#define int long long
#define lc (x<<1)
#define rc (x<<1|1)
using namespace std;
const int N=1e5+5;
inline bool in(int x,int l,int r){return x>=l&&x<=r;}
int c,n,m,q,idx,tn,X[N<<1],ans;
struct SEG{int lp[N<<4],rp[N<<4],sum[N<<4],len[N<<4];void build(int x,int l,int r){lp[x]=l,rp[x]=r;if(l==r) return;int mid=(l+r)>>1;build(lc,l,mid),build(rc,mid+1,r);}void pushup(int x){if(sum[x]) len[x]=X[rp[x]+1]-X[lp[x]];else len[x]=(lp[x]!=rp[x])*(len[lc]+len[rc]);}void chr(int x,int a,int b,int v){if(X[rp[x]+1]<=a||b<=X[lp[x]]) return;if(a<=X[lp[x]]&&X[rp[x]+1]<=b) sum[x]+=v;else chr(lc,a,b,v),chr(rc,a,b,v);pushup(x);}
}seg;
struct Line{int l,r,h,o;bool operator < (const Line &_) const{return h<_.h;}
}s[N<<1];
struct Hor{int y,l,r;};
struct Ver{int x,l,r;};
map<int,list<PII>> ks;//koishi
set<int> se;//visited
vector<Hor> hs;//horizon
vector<Ver> vs;//vertical
signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>c>>n>>m>>q; int op,x,y,xx,yy;while(q--){cin>>op>>x>>y>>xx>>yy;if(op==1){hs.eb(Hor{y,x,xx});s[++idx]={x-1,xx,y-1,1};s[++idx]={x-1,xx,y,-1};X[++tn]=x-1,X[++tn]=xx;}else if(op==2){vs.eb(Ver{x,y,yy});s[++idx]={x-1,x,y-1,1};s[++idx]={x-1,x,yy,-1};X[++tn]=x-1,X[++tn]=x;}else{ks[y-x].eb(x,xx);}}sort(s+1,s+1+idx);sort(X+1,X+1+tn),tn=unique(X+1,X+1+idx)-X-1;seg.build(1,1,tn-1);//处理横纵 for(int i=1;i<idx;i++){seg.chr(1,s[i].l,s[i].r,s[i].o);ans+=seg.len[1]*(s[i+1].h-s[i].h);}//处理斜向for(auto& koishi:ks){int p=koishi.first;auto &li=koishi.second;li.sort();for(auto it=li.begin(),lst=li.end();it!=li.end();){if(lst!=li.end()&&(*it).first<=(*lst).second){(*lst).second=max((*lst).second,(*it).second);li.erase(it++);}else lst=it++;}for(PII i:li){se.clear();for(Hor j:hs){if(in(j.y-p,i.first,i.second)&&in(j.y-p,j.l,j.r)){se.insert(j.y-p);}}for(Ver j:vs){if(in(j.x,i.first,i.second)&&in(j.x+p,j.l,j.r)){se.insert(j.x);}}ans+=i.second-i.first+1-se.size();}}cout<<ans<<"\n";return 0;
}