题目大意:考虑一个\(n \times
n\)的矩阵A,初始所有元素均为0.执行q次如下形式的操作:给定4个整数r,c,l,s,对于每个满足\(x∈[r,r+l),y∈[c,x−r+c]\)的元素(x,y),将权值增加s.也就是给一个左上顶点为(r,c)直角边长为l的下三角区域加上s.输出最终矩阵的元素异或和.
二维前缀和
考虑这么一个三角形:(假装有图.)
我们如果差分做的话,是对每一行的开头都加s对每一行的结尾的后一个数字都减去s
所以我们对查分数组再维护一个差分数组
对这个区域的(r,c)位置加上s,对竖着的(r+l,c)位置(结尾的下一行)减去s
对这个区域的(r,c+1)位置减去s,对他右下角再往右往下一个格子(r+l,c+l+1)加上s(因为本来是要对他们这种吊车尾减去s的嘛)
然后累加然后统计就好了
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| #include <bits/stdc++.h> #define int long long #define ll long long using namespace std;
const int N = 1e3 + 66;
int n, q, res; int cnm[N][N], fuck[N][N], a[N][N];
signed main() { int i, j, r, c, l, s; n = read(), q = read(); while (q --) { r = read(), c = read(), l = read(), s = read(); cnm[r][c] += s; cnm[min(r + l, n + 1)][c] -= s; fuck[r][c + 1] -= s; fuck[min(r + l, n + 1)][min(c + l + 1, n + 1)] += s; } for (i = 1; i <= n; ++ i) for (j = 1; j <= n; ++ j) { cnm[i][j] += cnm[i - 1][j]; fuck[i][j] += fuck[i - 1][j - 1]; } for (i = 1; i <= n; ++ i) for (j = 1; j <= n; ++ j) { a[i][j] = cnm[i][j] + a[i][j - 1] + fuck[i][j]; res ^= a[i][j]; } put(res); return 0; }
|
后记:
从没有见过此种类型题
第一次见,长见识了!