牛客多校第二场Jfarm(随机化算法)
题目大意:
有一块大小为n*m的农田,每一个地上都种着种类为a[i][j]的植物,接下来要进行T次农药喷洒,每次会对左上角为(x1,y1),右下角为(x2,y2)的矩阵喷洒类型为k的农药,如果被喷洒的植物的种类和农药的种类不同(也就是a[i][j]!=k),这个植物就会死掉。问在T次喷洒之后这n*m个植物有多少个死掉了。
思路:
如果喷洒的农药之和%它本身的种类!=0,植物肯定死掉了。而植物死掉了喷洒的农药之和%它本身的种类!=0则是个伪命题。比如植物种类为2,喷洒了1和3,种子死掉了,但是(1+3)%2=0.
如果我们想用这个方法来判断种子是否死掉了,可以先把hash处理数据,或者使用随机数,这样就不容易出现我们不想要的意外情况。
我们使用随机数来解决这个问题
#include <iostream>
#include <random>
#include <vector>
using namespace std;
vector<int> ran;//这是生成一个存放100w个随机数vector
vector<int> p[1000002];//存的是初始信息
vector<long long> f[1000002];//二维前缀和的信息
int main()
{
int n, m, t, tem, x1, x2, y1, y2, k;
long long ans = 0;
srand('!');//生成随机数种子
for (int i = 1000001; i >= 0; i--)
ran.push_back(rand() % 10010000 + 1000001);
scanf("%d%d%d", &n, &m, &t);
for (int i = 0; i <= n + 1; i++)
for (int j = 0; j <= m + 1; j++)
{
p[i].push_back(0);
f[i].push_back(0);
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
scanf("%d", &tem);
p[i][j] = ran[tem];
}
for (int i = 0; i < t; i++)//用二维前缀和更新区间
{
scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &k);
f[x1][y1] += ran[k];
f[x1][y2 + 1] -= ran[k];
f[x2 + 1][y1] -= ran[k];
f[x2 + 1][y2 + 1] += ran[k];
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
f[i][j] += f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1];
if (f[i][j] % p[i][j])
ans++;
}
printf("%lld\n", ans);
return 0;
}