B. The writing on the wall
题目链接:https://nanti.jisuanke.com/t/30991
题意:
给你一个n*m的矩阵, 其中有些格子上面有障碍物,问有多少个子矩阵满足里面不包含任何障碍物
思路:
经典题了,只要求出有多少个子矩阵包含障碍物然后减掉即可
暴力枚举每个障碍物,求出所有满足包含这个障碍物且这个障碍物上面和同一行左边都没有其它障碍物的子矩阵个数就可以了, 虽然障碍物有100000个,但是列只有100,所以每次直接暴力列,复杂度O(mk)
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 1000000007
typedef struct Res
{
int x, y;
bool operator < (const Res &b) const
{
if(x<b.x || x==b.x && y<b.y)
return 1;
return 0;
}
}Res;
Res s[200005];
int H[205];
int main(void)
{
LL ans, now;
int T, n, m, i, k, len, p, q, cas = 1;
scanf("%d", &T);
while(T--)
{
scanf("%d%d%d", &n, &m, &k);
ans = ((LL)n*(n-1)/2+n)*(m*(m-1)/2+m);
for(i=1;i<=k;i++)
scanf("%d%d", &s[i].x, &s[i].y);
H[0] = H[m+1] = 10000000;
for(i=1;i<=m;i++)
H[i] = 0;
sort(s+1, s+k+1);
for(i=1;i<=k;i++)
{
p = q = s[i].y;
len = s[i].x-H[p];
now = (LL)len;
while(p>1 || q<m)
{
if(H[p-1]<=H[q+1])
{
len = min(len, s[i].x-H[p-1]);
now += (LL)len*(q-s[i].y+1);
p--;
}
else
{
len = min(len, s[i].x-H[q+1]);
now += (LL)len*(s[i].y-p+1);
q++;
}
}
ans -= now*(n-s[i].x+1);
H[s[i].y] = s[i].x;
}
printf("Case #%d: %lld\n", cas++, ans);
}
return 0;
}