Paint by Letters P-题解
Paint by Letters P-题解
题意
一个
前置知识
欧拉平面图定理:
实现步骤
将可以一起染的连边,题目就是求联通块个数
点和边的数量很好求,二维前缀和就能办到,瓶颈在求区域数
我们先
噫!好!我们过了!
代码
#include<bits/stdc++.h>
#define Int long long int
#define Pub public
using std::min;using std::max;
int n,m,q;
char p[1005][1005];
std::pair<int,int> s[1005][1005][5];
bool vis[1005][1005],siv[2000005];
int v[1005][1005],e1[1005][1005],e2[1005][1005],r[1005][1005];
int rid[1005][1005],cnt;
std::pair<int,int> t[1000005];
void dfs(int x,int y){
if(x<0||x>n||y<0||y>m)return;
if(vis[x][y])return;
else vis[x][y]=1;
if(s[x][y][3]==std::pair<int,int>{0,0})rid[x][y-1]=rid[x][y],dfs(x,y-1);
if(s[x][y][4]==std::pair<int,int>{0,0})rid[x-1][y]=rid[x][y],dfs(x-1,y);
if(s[x+1][y+1][1]==std::pair<int,int>{0,0})rid[x][y+1]=rid[x][y],dfs(x,y+1);
if(s[x+1][y+1][2]==std::pair<int,int>{0,0})rid[x+1][y]=rid[x][y],dfs(x+1,y);
}
int main(){
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;++i)
for(int j=(getchar(),1);j<=m;++j)
p[i][j]=getchar();
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
int vvv=1,ee1=0,ee2=0;
if(p[i][j]==p[i-1][j])s[i][j][1]={i-1,j},++ee2;
if(p[i][j]==p[i][j-1])s[i][j][2]={i,j-1},++ee1;
if(p[i][j]==p[i+1][j])s[i][j][3]={i+1,j};
if(p[i][j]==p[i][j+1])s[i][j][4]={i,j+1};
v[i][j]=v[i-1][j]+v[i][j-1]-v[i-1][j-1]+vvv;
e1[i][j]=e1[i-1][j]+e1[i][j-1]-e1[i-1][j-1]+ee1;
e2[i][j]=e2[i-1][j]+e2[i][j-1]-e2[i-1][j-1]+ee2;
}
}
for(int i=0;i<=n;++i){
for(int j=0;j<=m;++j){
if(i==0&&j==0)r[i][j]=0;
else if(i==0||j==0)r[i][j]=1;
else r[i][j]+=r[i-1][j]+r[i][j-1]-r[i-1][j-1];
if(vis[i][j])continue;
else{
++cnt;
rid[i][j]=cnt;
t[cnt]=std::pair<int,int>{i,j};
++r[i][j];
dfs(i,j);
}
}
}
while(~--q){
memset(siv,0,sizeof(siv));
int x_,y_,_x,_y;
scanf("%d%d%d%d",&x_,&y_,&_x,&_y);
int ans=0;
ans+=v[_x][_y]+v[x_-1][y_-1]-v[x_-1][_y]-v[_x][y_-1];
ans-=e1[_x][_y]+e1[x_-1][y_]-e1[x_-1][_y]-e1[_x][y_];
ans-=e2[_x][_y]+e2[x_][y_-1]-e2[x_][_y]-e2[_x][y_-1];
ans+=r[_x-1][_y-1]+r[x_-1][y_-1]-r[x_-1][_y-1]-r[_x-1][y_-1];
for(int i=x_;i<_x;++i)
if(s[i][y_][3]==std::pair<int,int>{0,0})
if(t[rid[i][y_]].first>=x_&&t[rid[i][y_]].first<_x&&t[rid[i][y_]].second>=y_&&t[rid[i][y_]].second<_y&&!siv[rid[i][y_]])
siv[rid[i][y_]]=1,--ans;
for(int i=y_;i<_y;++i)
if(s[x_][i][4]==std::pair<int,int>{0,0})
if(t[rid[x_][i]].first>=x_&&t[rid[x_][i]].first<_x&&t[rid[x_][i]].second>=y_&&t[rid[x_][i]].second<_y&&!siv[rid[x_][i]])
siv[rid[x_][i]]=1,--ans;
for(int i=x_;i<_x;++i)
if(s[i][_y][3]==std::pair<int,int>{0,0})
if(t[rid[i][_y]].first>=x_&&t[rid[i][_y]].first<_x&&t[rid[i][_y]].second>=y_&&t[rid[i][_y]].second<_y&&!siv[rid[i][_y]])
siv[rid[i][_y]]=1,--ans;
for(int i=y_;i<_y;++i)
if(s[_x][i][4]==std::pair<int,int>{0,0})
if(t[rid[_x][i]].first>=x_&&t[rid[_x][i]].first<_x&&t[rid[_x][i]].second>=y_&&t[rid[_x][i]].second<_y&&!siv[rid[_x][i]])
siv[rid[_x][i]]=1,--ans;
printf("%d\n",ans);
}
return 0;
}