[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;
}
posted @ 2025-12-20 14:29  Oken喵~  阅读(1)  评论(0)    收藏  举报