[IOI 2024] 马赛克上色
有一个 \(n\) 行 \(n\) 列的矩阵 \(A\),初始时给定 \(a_{0,j}=x_j\) 和 \(a_{i,0}=y_i\),且保证 \(a_{i,j} \in \{0,1\}\)。对于 \(i,j \in [1,n)\),\(a_{i,j}=1\) 当且仅当 \(a_{i-1,j}=a_{i,j-1}=0\)。有 \(Q\) 次询问,第 \(k\) 次询问给定 \(0 \leq T_k \leq B_k < n\) 和 \(0 \leq U_k \leq D_k < n\),你需要回答 \(\sum\limits_{i=T_k}^{B_k} \sum\limits_{j=U_k}^{D_k} a_{i,j}\)。
\(1 \leq n,Q \leq 2 \times 10^5\)。
看起来条件难以刻画,考虑打表,我们先随机生成几个表:
\[\begin{bmatrix}
1 & 0 & 0 & 0 & 1 & 0 & 0 & 1 & 1 & 1 & 1 & 0 \\
0 & 1 & 0 & 1 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 1 \\
0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 \\
0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 \\
1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 \\
0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 \\
0 & 1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
1 & 0 & 1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1
\end{bmatrix}
\]
\[\begin{bmatrix}
0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 \\
0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 \\
1 & 0 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
1 & 0 & 1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 \\
1 & 0 & 0 & 1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 \\
1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 \\
1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 0 & 1 & 0 \\
0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 0 & 1 \\
0 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 0
\end{bmatrix}
\]
\[\begin{bmatrix}
1 & 0 & 0 & 1 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\
1 & 0 & 1 & 0 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 \\
0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 \\
0 & 1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
1 & 0 & 1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 \\
0 & 1 & 0 & 1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 \\
1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 \\
0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 0 & 1 & 0 \\
1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 0 & 1 \\
0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 0
\end{bmatrix}
\]
\[\begin{bmatrix}
1 & 0 & 0 & 1 & 0 & 0 & 0 & 1 & 0 & 1 & 0 & 0 \\
1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 \\
1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 \\
1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 \\
1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 \\
1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 \\
0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0
\end{bmatrix}
\]
\[\begin{bmatrix}
1 & 1 & 0 & 0 & 1 & 1 & 1 & 1 & 0 & 1 & 1 & 1 \\
1 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 \\
0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 \\
0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 \\
1 & 0 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\
0 & 1 & 0 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 \\
1 & 0 & 1 & 0 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 \\
1 & 0 & 0 & 1 & 0 & 0 & 1 & 0 & 0 & 1 & 0 & 1 \\
1 & 0 & 1 & 0 & 1 & 0 & 0 & 1 & 0 & 0 & 1 & 0
\end{bmatrix}
\]
我们可以得到结论:当 \(i,j \geq 2\) 时,\(a_{i+1,j+1}=a_{i,j}\)。
我们列出 \(a_{i,j}\) 附近的元素:
\[\begin{bmatrix}
a_{i-2,j-2} & a_{i-2,j-1} & a_{i-2,j} & a_{i-2,j+1} \\
a_{i-1,j-2} & a_{i-1,j-1} & a_{i-1,j} & a_{i-1,j+1} \\
a_{i,j-2} & a_{i,j-1} & a_{i,j} & a_{i,j+1} \\
a_{i+1,j-2} & a_{i+1,j-1} & a_{i+1,j} & a_{i+1,j+1}
\end{bmatrix}
\]
容易发现这些位置一定都存在,接下来进行分类讨论:
- 若 \(a_{i,j}=1\),则 \(a_{i,j+1}=a_{i+1,j}=0\),可得 \(a_{i+1,j+1}=1=a_{i,j}\)。
\[\begin{bmatrix}
a_{i-2,j-2} & a_{i-2,j-1} & a_{i-2,j} & a_{i-2,j+1} \\
a_{i-1,j-2} & a_{i-1,j-1} & a_{i-1,j} & a_{i-1,j+1} \\
a_{i,j-2} & a_{i,j-1} & 1 & 0 \\
a_{i+1,j-2} & a_{i+1,j-1} & 0 & 1
\end{bmatrix}
\]
- 若 \(a_{i,j}=0\),考虑反证。此时若 \(a_{i+1,j+1}=1\),则 \(a_{i,j+1}=a_{i+1,j}=0\),可得 \(a_{i-1,j+1}=a_{i+1,j-1}=1\),进而有 \(a_{i-2,j+1}=a_{i-1,j}=a_{i,j-1}=a_{i+1,j-2}=0\),此时 \(a_{i,j}=1\),矛盾。
\[\begin{bmatrix}
a_{i-2,j-2} & a_{i-2,j-1} & a_{i-2,j} & 0 \\
a_{i-1,j-2} & a_{i-1,j-1} & \color{red}{0} & 1 \\
a_{i,j-2} & \color{red}{0} & \color{red}{0} & 0 \\
0 & 1 & 0 & 1
\end{bmatrix}
\]
于是我们可以对于所有的 \(\min(i,j) \leq 2\) 求出 \(a_{i,j}\),查询时进行大分讨即可。
具体地,你发现对于 \(i,j \geq 2\) 的情况,可以拆成若干斜条进行分组求和,具体细节见代码。
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
int n,q,a_x[3][200000],a_y[200000][3];
long long sum_x[3][200000],sum_y[200000][3],sum_xx[200000],sum_yy[200000];
long long query(int x,int y){
if(x<=2){
long long ans=0;
for(int i=0;i<=x;i++){
ans+=sum_x[i][y];
}
return ans;
}
if(y<=2){
long long ans=0;
for(int j=0;j<=y;j++){
ans+=sum_y[x][j];
}
return ans;
}
long long ans=0;
ans+=sum_x[0][y]+sum_x[1][y];
ans+=sum_y[x][0]+sum_y[x][1];
ans-=sum_x[0][1]+sum_x[1][1];
if(x>=y){
int l=2,r=2+x-y;
ans+=(sum_y[r][2]-sum_y[l-1][2])*(y-1);
ans+=(sum_y[x][2]-sum_y[r][2])*(x+1)-(sum_xx[x]-sum_xx[r]);
ans+=(sum_x[2][y]-sum_x[2][2])*(y+1)-(sum_yy[y]-sum_yy[2]);
}
else{
int l=2,r=2+y-x;
ans+=(sum_x[2][r]-sum_x[2][l-1])*(x-1);
ans+=(sum_x[2][y]-sum_x[2][r])*(y+1)-(sum_yy[y]-sum_yy[r]);
ans+=(sum_y[x][2]-sum_y[2][2])*(x+1)-(sum_xx[x]-sum_xx[2]);
}
return ans;
}
vector<long long> mosaic(vector<int> X,vector<int> Y,vector<int> T,vector<int> B,vector<int> L,vector<int> R){
n=X.size(),q=T.size();
for(int j=0;j<n;j++){
a_x[0][j]=X[j];
sum_x[0][j]=X[j];
if(j>0) sum_x[0][j]+=sum_x[0][j-1];
}
for(int i=1;i<min(n,3);i++){
a_x[i][0]=Y[i];
sum_x[i][0]=Y[i];
for(int j=1;j<n;j++){
if(a_x[i-1][j]==0 && a_x[i][j-1]==0){
a_x[i][j]=1;
}
sum_x[i][j]=sum_x[i][j-1]+a_x[i][j];
}
}
for(int i=0;i<n;i++){
a_y[i][0]=Y[i];
sum_y[i][0]=Y[i];
if(i>=1) sum_y[i][0]+=sum_y[i-1][0];
}
for(int j=1;j<min(n,3);j++){
a_y[0][j]=X[j];
sum_y[0][j]=X[j];
for(int i=1;i<n;i++){
if(a_y[i-1][j]==0 && a_y[i][j-1]==0){
a_y[i][j]=1;
}
sum_y[i][j]=sum_y[i-1][j]+a_y[i][j];
}
}
for(int i=0;i<n;i++){
sum_xx[i]=a_y[i][2]*i;
if(i>=1) sum_xx[i]+=sum_xx[i-1];
}
for(int i=0;i<n;i++){
sum_yy[i]=a_x[2][i]*i;
if(i>=1) sum_yy[i]+=sum_yy[i-1];
}
vector<long long> ans;
for(int k=0;k<q;k++){
long long pre_ans=0;
if(T[k]>=0 && L[k]>=0) pre_ans+=query(B[k],R[k]);
if(T[k]>=1 && L[k]>=0) pre_ans-=query(T[k]-1,R[k]);
if(T[k]>=0 && L[k]>=1) pre_ans-=query(B[k],L[k]-1);
if(T[k]>=1 && L[k]>=1) pre_ans+=query(T[k]-1,L[k]-1);
ans.push_back(pre_ans);
}
return ans;
}

浙公网安备 33010602011771号