版权声明:是自己手打的没错 https://blog.csdn.net/Mr_Treeeee/article/details/82934112
https://acm.ecnu.edu.cn/contest/113/problem/C/
POINT:
用 表示第i行有多少个 0,用 表示第 j 列有多少个 0,bij 表示第 i 行第 j 列是否为 0。则 cost(i,j)=+−。
设C为全矩阵0的个数。
同理求和2cb=2c^2。
所以得
每次修改操作至多只会影响一个 ci 和一个 ri,将原来的 ci,ri,C 的贡献撤回,然后重新计算贡献即可。
对原题解做了一些补充,注意取模。
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <vector>
#include <map>
using namespace std;
const int N = 2e5 + 10;
typedef pair<int,int> pii;
#define LL long long
const LL mod = 1e9+7;
map<pii,int> mp;
LL r[N],c[N];
int main()
{
LL n,k,Q;
scanf("%lld%lld%lld",&n,&k,&Q);
LL C=(n*n%mod-k+mod)%mod;
for(LL i=1;i<=n;i++) r[i]=c[i]=n;
for(LL i=1;i<=k;i++){
LL x,y;scanf("%lld%lld",&x,&y);
mp[make_pair(x,y)]=1;
r[x]--;c[y]--;
}
LL ans=0;
LL a=0,b=0;
for(LL i=1;i<=n;i++){
a+=c[i]*c[i];
a%=mod;
b+=r[i]*r[i];
b%=mod;
}
ans=(n-2)*(a+b)%mod+2*C*C%mod+C;
ans%=mod;
printf("%lld\n",ans);
while(Q--){
LL x,y;scanf("%lld%lld",&x,&y);
ans-=((n-2)*(r[x]*r[x]%mod+c[y]*c[y]%mod)%mod+2*C*C%mod+C)%mod;
ans=(ans+mod)%mod;
if(mp[make_pair(x,y)]==1){
r[x]++;c[y]++;C++;
ans+=((n-2)*(r[x]*r[x]%mod+c[y]*c[y]%mod)%mod+2*C*C%mod+C)%mod;
ans%=mod;
mp[make_pair(x,y)]=0;
}else{
r[x]--;c[y]--;C--;
C=(C+mod)%mod;
ans+=((n-2)*(r[x]*r[x]%mod+c[y]*c[y]%mod)%mod+2*C*C%mod+C)%mod;
ans%=mod;
mp[make_pair(x,y)]=1;
}
printf("%lld\n",ans);
}
return 0;
}