【USACO 2021JAN P】Paint by Letters

【USACO 2021JAN P】Paint by Letters

by AmanoKumiko

Description

给出\(N*M\)的矩阵,每个点有一个颜色

颜色相同且相邻的点连N边

\(Q\)组询问,每次询问一个子矩阵中的连通块数量

Input

第一行\(N\)\(M\)\(Q\)

以下\(N\)\(M\)列表示矩阵

以下\(Q\)行每行四个整数\(x1,y1,x2,y2\)表示子矩阵

Output

\(Q\)行,表示答案

Sample Input

4 8 9
ABBAAAAA
ABAAAABA
CAADABBA
AAAAAAAA
1 1 4 8
3 5 3 8
1 3 2 4
1 4 2 5
1 1 3 3
4 4 4 4
2 6 4 8
3 5 4 6
1 6 3 8

Sample Output

6
3
2
1
4
1
3
2
2

Data Constraint

\(1 \le N,M,Q \le 10^3\)

Solution

定理题。。。

欧拉定理:\(V-E+F=C+1\)

\(V\)为点数,很好算

\(E\)为边数,很好算

\(F\)为区域数,为处理重点

首先搜出所有的区域,对于每个区域,随便选择一个标记点,把区域贡献加在标记点上,然后二维前缀和一下

对于一个询问,先算出子矩阵中区域的贡献数

然后枚举子矩阵的边界,若当前点所属的区域的标记点在子矩阵内,说明此区域属与外界连通,属于无界域,所以减掉它的贡献,开桶防算重

Code

#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a;i<=b;i++)
#define Fd(i,a,b) for(int i=a;i>=b;i--)
#define N 1010

char s[N];
struct node{int x,y;}pos[N*N];
queue<node>p;
int n,m,q,a[N][N],e[N][N][2],f[N][N],way[4][2],line[N][N][4],be[N][N],cnt,stx,sty,enx,eny,tot[N*N],ans;

bool in(node v){return v.x>=stx&&v.x<=enx-1&&v.y>=sty&&v.y<=eny-1;}

void ins(int S){if(!tot[S])ans--;tot[S]++;}

void dec(int S){tot[S]--;}

int main(){
	way[0][0]=way[1][1]=1;way[2][0]=way[3][1]=-1;
	scanf("%d%d%d",&n,&m,&q);
	F(i,1,n){scanf("%s",s+1);F(j,1,m)a[i][j]=s[j]-'A'+1;}
	F(i,1,n) F(j,1,m) F(fx,0,3){
		int xx=i+way[fx][0],yy=j+way[fx][1];
		if(a[xx][yy]==a[i][j]&&fx<2)e[i][j][fx]++;
	}
	F(i,1,n-1) F(j,1,m-1)if(!be[i][j]){
		bool out=0;node lst;p.push((node){i,j});be[i][j]=++cnt;
		while(!p.empty()){
			node now=p.front();p.pop();lst=now;
			F(fx,0,3){
				int xx=now.x+way[fx][0],yy=now.y+way[fx][1];
				if(xx<1||yy<1||xx>=n||yy>=m){
					if(fx==0&&!e[now.x+1][now.y][1])out=1;
					if(fx==1&&!e[now.x][now.y+1][0])out=1;
					if(fx==2&&!e[now.x][now.y][1])out=1;
					if(fx==3&&!e[now.x][now.y][0])out=1;
					continue;
				}
				if(be[xx][yy])continue;
				if(fx==0&&e[now.x+1][now.y][1])continue;
				if(fx==1&&e[now.x][now.y+1][0])continue;
				if(fx==2&&e[now.x][now.y][1])continue;
				if(fx==3&&e[now.x][now.y][0])continue;
				be[xx][yy]=cnt;p.push((node){xx,yy});
			}
		}
		if(!out)f[lst.x][lst.y]++,pos[cnt]=lst;
	}
	F(i,1,n) F(j,1,m) F(fx,0,1)e[i][j][fx]+=e[i-1][j][fx]+e[i][j-1][fx]-e[i-1][j-1][fx];
	F(i,1,n-1) F(j,1,m-1)f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
	F(i,1,q){
		ans=0;
		scanf("%d%d%d%d",&stx,&sty,&enx,&eny);
		ans+=(enx-stx+1)*(eny-sty+1);
		ans-=e[enx-1][eny][0]-e[enx-1][sty-1][0]-e[stx-1][eny][0]+e[stx-1][sty-1][0];
		ans-=e[enx][eny-1][1]-e[enx][sty-1][1]-e[stx-1][eny-1][1]+e[stx-1][sty-1][1];
		if(stx==enx||sty==eny){printf("%d\n",ans);continue;}
		ans+=f[enx-1][eny-1]-f[enx-1][sty-1]-f[stx-1][eny-1]+f[stx-1][sty-1];
		F(j,max(1,sty-1),min(m-1,eny+1)){
			if(stx&&in(pos[be[stx-1][j]]))ins(be[stx-1][j]);
			if(enx<=n-1&&in(pos[be[enx][j]]))ins(be[enx][j]);
		}
		F(j,stx,enx-1){
			if(sty&&in(pos[be[j][sty-1]]))ins(be[j][sty-1]);
			if(eny<=m-1&&in(pos[be[j][eny]]))ins(be[j][eny]);
		}
		printf("%d\n",ans);
		F(j,max(1,sty-1),min(m-1,eny+1)){
			if(stx&&in(pos[be[stx-1][j]]))dec(be[stx-1][j]);
			if(enx<=n-1&&in(pos[be[enx][j]]))dec(be[enx][j]);
		}
		F(j,stx,enx-1){
			if(sty&&in(pos[be[j][sty-1]]))dec(be[j][sty-1]);
			if(eny<=m-1&&in(pos[be[j][eny]]))dec(be[j][eny]);
		}
	}
	return 0;
}
posted @ 2021-08-19 21:03  冰雾  阅读(79)  评论(0编辑  收藏  举报