【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;
}