get两个知识点:
1、随机化过题
2、如果有Q次修改区间值的操作,如何快速求出修改后每个位置的值
随机化的话,首先,对于这题,我们有这么一个想法:修改后的值 = 修改次数 * 初始值,那么这颗植物是很有可能活下来的。显然,直接这么写用脚都能hack掉,比如如果 8 = 4 + 4,那么显然也可以有 8 = 2 + 6, 那么怎么办?随机打乱一下,不妨设4 -> 6, 2 - >3, 6 -> 5,那么上面就变成了 12 = 6 + 6, 8 = 3 + 5,大大降低了被hack的几率。
对于一维的来说,[L,R] 加上k等价于 a[L] += k, a[R + 1] -= k,然后累加之后就是改变了多少值,再加上原先的值就是答案。理由如下,因为它是求的前缀和,那么对于L之后的一定都要加上k,R之后的就不能再加了,所以要减去。二维的话也可以类似的推广过去。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2002000;
ll mp[N], g[N], change[N], vis[N];
int main(){
int n, m, t;
scanf("%d %d %d", &n, &m, &t);
for(int i = 1; i <= n * m; i ++){
mp[i] = i;
}
random_shuffle(mp + 1, mp + n * m + 1);
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= m; j ++){
scanf("%lld", &g[i * m + j]);
g[i * m + j] = mp[g[i * m + j]];
}
}
int x1, y1, x2, y2, k;
while(t --){
scanf("%d %d %d %d %d", &x1, &y1, &x2, &y2, &k);
k = mp[k];
change[x1 * m + y1] += k, change[(x2 + 1) * m + y2 + 1] += k;
change[(x2 + 1) * m + y1] -= k, change[x1 * m + y2 + 1] -= k;
vis[x1 * m + y1] ++, vis[(x2 + 1) * m + y2 + 1] ++;
vis[(x2 + 1) * m + y1] --, vis[x1 * m + y2 + 1] --;
}
int tot = 0;
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= m; j ++){
change[i * m + j] += change[(i - 1) * m + j] + change[i * m + j - 1] - change[(i - 1) * m + j - 1];
vis[i * m + j] += vis[(i - 1) * m + j] + vis[i * m + j - 1] - vis[(i - 1) * m + j - 1];
if(change[i * m + j] != vis[i * m + j] * g[i * m + j])
tot ++;
}
}
printf("%d\n", tot);
return 0;
}