Luogu9478 方格染色

Arahc 11.0

题面

nnmm 列的格子。有三种染色,横着竖着斜着染一条。染完问你染到了多少个点。

n,m109n,m\leq 10^9,染色次数 105\leq 10^5,斜着染次数不超过 55

题解

不超过五次的斜着染看起来就是附加条件,让他和春测题不重复。最后居然是染完再问你有多少个点,一眼离线,离线就可以把所有重叠的横着竖着斜着分别拼起来了。

显然先考虑只有横着和竖着的情况。可以认为把横线都打上去,然后依次看每个竖线,询问这个竖线和横线有多少个交点。这个操作一眼离散化扫描线。好了,你已经有 8585 分了。

现在考虑斜线有什么影响。显然,对于一条特定的斜线和一条特定的横线或竖线只会交在一个点。但是这样做你要枚举每个斜线和每个直线啊?没关系,一共只有五条斜线。对于三线共点的情况,斜线会分别和横竖线都算一次,这个 map 判掉就好了。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#include<bits/stdc++.h>
#define elif else if
#define int long long
#ifdef DEBUG
# define debug(...) fprintf(stderr,__VA_ARGS__)
#else
# define debug
#endif
using namespace std;
bool Begin;
const int max_n=100005;
inline int read(){
int x=0;bool w=0;char c=getchar();
while(!isdigit(c)) w|=c=='-',c=getchar();
while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=getchar();
return w?-x:x;
}
inline void write(int x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10^48);
}

int Q,ta,tb,tc;

struct Horz{
int l,r,y;
Horz(int Y=0,int L=0,int R=0):y(Y),l(L),r(R){}
bool operator < (const Horz &b) const{
Horz a=*this;
if(a.y!=b.y) return a.y<b.y;
if(a.l!=b.l) return a.l<b.l;
return a.r<b.r;
}
}A[max_n];
vector<Horz> a;
struct Vert{
int l,r,x;
Vert(int X=0,int L=0,int R=0):x(X),l(L),r(R){}
bool operator < (const Vert &b) const{
Vert a=*this;
if(a.x!=b.x) return a.x<b.x;
if(a.l!=b.l) return a.l<b.l;
return a.r<b.r;
}
}B[max_n];
vector<Vert> b;
struct Lean{
int x,y,len;
Lean(int X=0,int Y=0,int L=0):x(X),y(Y),len(L){}
bool operator < (const Lean &b) const{
Lean a=*this;
return a.x<b.x;
}
}C[6];
vector<Lean> c;

inline void Init(){
sort(A+1,A+1+ta),sort(B+1,B+1+tb),sort(C+1,C+1+tc);
for(int i=1,l=A[1].l,r=A[1].r;i<=ta;++i){
if(i!=1 && A[i].y!=A[i-1].y){
a.emplace_back(A[i-1].y,l,r);
l=A[i].l,r=A[i].r;
}
elif(i!=1 && A[i].l>r+1){
a.emplace_back(A[i].y,l,r);
l=A[i].l,r=A[i].r;
}
elif(i!=1){
r=max(r,A[i].r);
}
if(i==ta){
a.emplace_back(A[i].y,l,r);
break;
}
}
for(int i=1,l=B[1].l,r=B[1].r;i<=tb;++i){
if(i!=1 && B[i].x!=B[i-1].x){
b.emplace_back(B[i-1].x,l,r);
l=B[i].l,r=B[i].r;
}
elif(i!=1 && B[i].l>r+1){
b.emplace_back(B[i].x,l,r);
l=B[i].l,r=B[i].r;
}
elif(i!=1){
r=max(r,B[i].r);
}
if(i==tb){
b.emplace_back(B[i].x,l,r);
break;
}
}
bool delc[6]={0,0,0,0,0,0};
for(int i=1;i<=tc;++i)
for(int j=i+1;j<=tc;++j) if(!delc[j] && C[j].x-C[i].x==C[j].y-C[i].y && C[j].x<=C[i].x+C[i].len+1){
delc[j]=1;
C[i].len=max(C[i].len,C[j].x+C[j].len-C[i].x);
}
for(int i=1;i<=tc;++i) if(!delc[i])
c.emplace_back(C[i]);
}

int srt[max_n<<1],tot;
struct Scan{
int l,r,x;
Scan(int L=0,int R=0,int X=0):l(L),r(R),x(X){}
bool operator < (const Scan &b) const{
Scan a=*this;
if(a.x!=b.x) return a.x<b.x;
if(a.l!=b.l) return a.l<b.l;
return a.r<b.r;
}
};
vector<Scan> scan;
class SegmentTree{
private:
int L[max_n<<3],R[max_n<<3];
int sm[max_n<<3],ln[max_n<<3];
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
inline void pushup(int x){
if(sm[x]) ln[x]=srt[R[x]+1]-srt[L[x]];
else ln[x]=ln[ls(x)]+ln[rs(x)];
}
public:
inline void build(int x,int l,int r){
L[x]=l,R[x]=r,sm[x]=ln[x]=0;
if(l==r) return;
int mid=(l+r)>>1;
build(ls(x),l,mid),build(rs(x),mid+1,r);
}
inline void add(int x,int l,int r,int val){
if(srt[R[x]+1]<=l || r<=srt[L[x]]) return;
if(l<=srt[L[x]] && srt[R[x]+1]<=r){
sm[x]+=val;
return pushup(x);
}
int mid=(L[x]+R[x])>>1;
if(l<=srt[mid]) add(ls(x),l,r,val);
if(r>srt[mid+1]) add(rs(x),l,r,val);
pushup(x);
}
inline int ask(int x){
return ln[x];
}
}seg;
inline int ScanLine(){
for(auto hor:a){
srt[++tot]=hor.y,srt[++tot]=hor.y+1;
scan.emplace_back(hor.y,hor.y+1,hor.l);
scan.emplace_back(-hor.y,-hor.y-1,hor.r+1);
}
for(auto ver:b){
srt[++tot]=ver.l,srt[++tot]=ver.r+1;
scan.emplace_back(ver.l,ver.r+1,ver.x);
scan.emplace_back(-ver.l,-ver.r-1,ver.x+1);
}
sort(srt+1,srt+1+tot);
sort(scan.begin(),scan.end());
tot=unique(srt,srt+1+tot)-srt-1;
seg.build(1,1,tot-1);
int res=0;
for(int i=0;i<scan.size()-1;++i){
int val=1;
if(scan[i].l<0)
scan[i].l=-scan[i].l,scan[i].r=-scan[i].r,val=-val;
seg.add(1,scan[i].l,scan[i].r,val);
res+=(scan[i+1].x-scan[i].x)*seg.ask(1);
}
return res;
}

map<pair<int,int>,bool> mp;
inline bool In(int l,int mid,int r){return l<=mid && mid<=r;}
inline int LeanLine(){
for(auto le:c){
for(auto ho:a)
if(In(le.y,ho.y,le.y+le.len) && In(ho.l,ho.y-le.y+le.x,ho.r))
mp[make_pair(ho.y-le.y+le.x,ho.y)]=1;
for(auto ve:b)
if(In(le.x,ve.x,le.x+le.len) && In(ve.l,ve.x-le.x+le.y,ve.r))
mp[make_pair(ve.x,ve.x-le.x+le.y)]=1;
}
return mp.size();
}

bool End;
#define File "color"
signed main(){
#ifndef ONLINE_JUDGE
freopen(File ".in","r",stdin);
freopen(File ".out","w",stdout);
#endif
debug("Memory : %lf\n",(&Begin-&End)/1024.0/1024);
int Useless=read();Useless=read(),Useless=read();
Q=read();
for(int i=1;i<=Q;++i){
int tp=read(),xa=read(),ya=read(),xb=read(),yb=read();
if(tp==1)
A[++ta]=Horz(ya,xa,xb);
elif(tp==2)
B[++tb]=Vert(xa,ya,yb);
else
C[++tc]=Lean(xa,ya,xb-xa);
}
Init();
int ans1=ScanLine(),ans2=-LeanLine();
for(auto lea:c)
ans2+=lea.len+1;
write(ans1+ans2),putchar('\n');
return 0;
}
  • 标题: Luogu9478 方格染色
  • 作者: Arahc
  • 创建于 : 2023-08-02 08:00:00
  • 更新于 : 2023-08-02 10:06:42
  • 链接: https://arahc.github.io/2023/08/02/【题解】Luogu9478-方格染色/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
目录
Luogu9478 方格染色