https://csacademy.com/contest/archive/task/rooms/statement/
注意到每个rooms都是连续的,那么我们可以给每个room设定一个代表点,那么对于一个矩形中的所有room,分为两种分别是代表点在矩形中的,第二种是代表点在矩形外面的,但是矩形外面要进来的,必须经过边界,那么我们只要枚举边界上的点看他的代表点在不在矩形内就行了,再搞个vis数组记录一下看已经加进答案了没
#include<bits/stdc++.h>
using namespace std;
const int maxl=2e3+10;
int n,m,tot;
int tx[5]={0,0,0,1,-1};
int ty[5]={0,1,-1,0,0};
struct node
{
int x,y;
}b[maxl*maxl];
int c[maxl][maxl];
int sum[maxl][maxl];
char a[maxl][maxl];
bool vis[maxl*maxl];
inline void bfs(int sx,int sy,char d)
{
queue<node> q;
c[sx][sy]=tot;q.push(node{sx,sy});
while(!q.empty())
{
int x=q.front().x,y=q.front().y;
q.pop();
for(int i=1;i<=4;i++)
{
int xx=x+tx[i],yy=y+ty[i];
if(c[xx][yy] || xx<=0 || xx>n || yy<=0 || yy>m || a[xx][yy]!=d)
continue;
c[xx][yy]=tot;
q.push(node{xx,yy});
}
}
}
inline bool in(int col,int x1,int y1,int x2,int y2)
{
return (b[col].x>=x1 && b[col].x<=x2 && b[col].y>=y1 && b[col].y<=y2) || vis[col];
}
inline void print()
{
printf("%d\n",tot);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
printf("%d%c",c[i][j]," \n"[j==m]);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%s",a[i]+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(!c[i][j])
{
++tot;sum[i][j]=1;
b[tot]=node{i,j};
bfs(i,j,a[i][j]);
//print();
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
sum[i][j]+=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1];
scanf("%d",&m);
while(m--)
{
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
int ans=sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1];
vector<int> tmp;
for(int j=y1;j<=y2;j++)
{
if(!in(c[x1][j],x1,y1,x2,y2))
ans++,tmp.push_back(c[x1][j]),vis[c[x1][j]]=true;
if(!in(c[x2][j],x1,y1,x2,y2))
ans++,tmp.push_back(c[x2][j]),vis[c[x2][j]]=true;
}
for(int i=x1+1;i<=x2-1;i++)
{
if(!in(c[i][y1],x1,y1,x2,y2))
ans++,tmp.push_back(c[i][y1]),vis[c[i][y1]]=true;
if(!in(c[i][y2],x1,y1,x2,y2))
ans++,tmp.push_back(c[i][y2]),vis[c[i][y2]]=true;
}
printf("%d\n",ans);
for(int col:tmp)
vis[col]=false;
}
return 0;
}