2018牛客多校第二场j

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;
	}

猜你喜欢

转载自blog.csdn.net/qq_38759433/article/details/81448893