思路:
学习了网上大部分思路,总结如下:
多加零行零列,这样相当于n+1行,m+1列,一共能形成的长方形数,就是从行中挑两条线,从列中挑两条线相交形成的一矩形
然后减去包含奇数个炸弹点的矩形区域,加上包含偶数个炸弹点的区域。区域用左下和右上点表示,然后行的两条线就是从最小行以下和最大行以上挑选了,列同理
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e4 + 10;
ll n,m,k;
const int inf = 0x3f3f3f3f;
struct Node
{
ll x,y;
} node[maxn];
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>m>>k;
for(int i = 0 ; i < k ; i++)
{
cin>>node[i].x>>node[i].y;
}
ll sum = (n+1)*n/2 *(m+1)*m / 2;
//cout<<"sum"<<sum<<endl;
for(int i = 1 ; i < (1<<k) ; i++)
{
ll num = 0;
ll minx = 100000000;
ll miny = 100000000;
ll maxx = 0;
ll maxy = 0;
for(int j = 0; j < k; j++)
{
if((1<<j) &i )
{
num++;
minx = min(minx,node[j].x);
miny = min(miny,node[j].y);
maxx = max(maxx,node[j].x);
maxy = max(maxy,node[j].y);
}
}
// cout<<minx<<' '<<miny<<' '<<maxx<<' ' <<maxy<<endl;
ll tmp = minx*miny * (n - maxx+1)*(m - maxy+1);
// cout<<"Tmp:"<<tmp<<endl;
if(num&1) sum-=tmp;
else sum+=tmp;
}
cout<<sum<<endl;
}
return 0;
}