[EOJ Monthly 2018.10][C. 痛苦的 01 矩阵]

时间:2023-03-09 00:04:33
[EOJ Monthly 2018.10][C. 痛苦的 01 矩阵]

题目链接:C. 痛苦的 01 矩阵

题目大意:原题说的很清楚了,不需要简化_(:з」∠)_

题解:设\(r_i\)为第\(i\)行中0的个数,\(c_j\)为第\(j\)列中0的个数,\(f_{i,j}\)代表对应格子是否为0,则有\(cost(i,j)=r_i+c_j-f_{i,j}\),\((cost(i,j))^2=r_i^2+c_j^2+f_{i,j}+2r_ic_j-2f_{i,j}(r_i+c_j)\)

$$\sum_{i=1}^n \sum_{j=1}^n \left( cost(i,j) \right)^2 = \sum_{i=1}^n (r_i^2+c_i^2)+\sum_{i=1}^n \sum_{j=1}^nf_{i,j}+2(\sum_{i=1}^nr_i)(\sum_{j=1}^nc_j)-2f_{i,j}\sum_{i=1}^n \sum_{j=1}^n(r_i+c_j)$$

   初始状态下,\(ans=n^2*(2n-1)^2, r_i=c_i=n\),给出\(k\)个为1的方格可以看做进行\(k\)次反转操作,之后把式子中的每一项一一对应地进行修改就好了

#include<bits/stdc++.h>
using namespace std;
#define N 200001
#define LL long long
#define MOD 1000000007
LL n,k,q,x,y,u,v,r[N],sr[N],c[N],sc[N],ans;
set<LL>s;
void add(LL x,LL y)
{
s.insert(x*N+y);
r[x]--,c[y]--;
ans+=MOD-n*(2ll*r[x]+)%MOD,ans%=MOD;
ans+=MOD-n*(2ll*c[y]+)%MOD,ans%=MOD;
ans+=MOD-,ans%=MOD;
ans+=2ll*(MOD-sc[n]+MOD-sr[n]+),ans%=MOD;
ans+=2ll*(r[x]++c[y]+)%MOD,ans%=MOD;
ans+=2ll*r[x]%MOD+2ll*c[y]%MOD,ans%=MOD;
sc[n]--,sr[n]--;
}
void del(LL x,LL y)
{
sc[n]++,sr[n]++;
ans+=MOD-(2ll*r[x]%MOD+2ll*c[y]%MOD)%MOD,ans%=MOD;
ans+=MOD-(2ll*(r[x]++c[y]+)%MOD)%MOD,ans%=MOD;
ans+=2ll*(sc[n]+sr[n]-)%MOD,ans%=MOD;
ans++,ans%=MOD;
ans+=n*(2ll*c[y]+)%MOD,ans%=MOD;
ans+=n*(2ll*r[x]+)%MOD,ans%=MOD;
r[x]++,c[y]++;
s.erase(x*N+y);
}
int main()
{
scanf("%lld%lld%lld",&n,&k,&q);
for(LL i=;i<=n;i++)
{
r[i]=c[i]=n;
sr[i]=(sr[i-]+r[i])%MOD;
sc[i]=(sc[i-]+c[i])%MOD;
}
ans=4ll*n*n-4ll*n+,ans%=MOD;
ans*=n*n%MOD,ans%=MOD;
for(LL i=;i<=k;i++)
scanf("%lld%lld",&x,&y),add(x,y);
printf("%lld\n",ans);
for(LL i=;i<=q;i++)
{
scanf("%lld%lld",&u,&v);
if(s.count(u*N+v))del(u,v);
else add(u,v);
printf("%lld\n",ans);
}
return ;
}