[agc015c]Nuske vs Phantom Thnook

来源:互联网 发布:mac剪辑电影软件 编辑:程序博客网 时间:2024/06/10 00:10

前言

一开始想了无特殊性做法。
后来才用到树的性质QAQ

题目大意

一个蓝白网格图,保证蓝格子连成森林。
每次选取一个子矩阵问蓝联通块个数。

做法

森林联通块数=点数-边数。
于是很好做。

#include<cstdio>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;const int maxn=2000+10;int s[maxn][maxn],sum[maxn][maxn],num[maxn][maxn];int i,j,k,l,t,n,m,q,x,y,u,v,ans;char get(){    char ch=getchar();    while (ch!='1'&&ch!='0') ch=getchar();    return ch;}int main(){    scanf("%d%d%d",&n,&m,&q);    fo(i,1,n)        fo(j,1,m)            s[i][j]=get()-'0';    fo(i,1,n)        fo(j,1,m){            sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];            if (j>1) sum[i][j]+=(s[i][j]&&s[i][j-1]);            num[i][j]=num[i-1][j]+num[i][j-1]-num[i-1][j-1];            if (i>1) num[i][j]+=(s[i][j]&&s[i-1][j]);        }    fo(i,1,n)        fo(j,1,m)            s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];    while (q--){        scanf("%d%d%d%d",&x,&y,&u,&v);        ans=s[u][v]-s[x-1][v]-s[u][y-1]+s[x-1][y-1];        y++;        t=sum[u][v]-sum[x-1][v]-sum[u][y-1]+sum[x-1][y-1];        ans-=t;        y--;        x++;        t=num[u][v]-num[x-1][v]-num[u][y-1]+num[x-1][y-1];        ans-=t;        x--;        printf("%d\n",ans);    }}