1. 程式人生 > >Problem 3 二維差分

Problem 3 二維差分

操作 for 就是 三角形 namespace swe 給定 sin std

$des$

考慮一個 n ∗ 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。
輸出最終矩陣的元素異或和。

技術分享圖片

$sol$

每次加減是一個等腰直角三角形

考慮對每行查分

即對垂直於 x 軸的腰上的每個點 +1 ,所有斜邊的後一個點 -1

這樣的話,每行形成了查分數組

簡化上面的過程

對腰上的點 +1 時同樣也可以查分進行

對斜邊上的點同理,只不過還原時 $a_{i, j} += a_{i - 1, j - 1}$

註意判斷邊界條件

$code$

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>

using namespace std;
const int N = 2010;

#define
gc getchar() inline int read() { int x = 0; char c = gc; while(c < 0 || c > 9) c = gc; while(c >= 0 && c <= 9) x = x * 10 + c - 0, c = gc; return x; } #undef gc #define Rep(i, a, b) for(int i = a; i <= b; i ++) #define LL long long LL add[N][N], cut[N][N];
struct Node { int r, c, l, s; } Ask[(int)3e5 + 10]; int n, q; LL A[N][N], B[N][N]; int main() { n = read(), q = read(); Rep(qq, 1, q) Ask[qq] = (Node) { read(), read(), read(), read() }; Rep(i, 1, q) { int r = Ask[i].r, c = Ask[i].c, l = Ask[i].l, s = Ask[i].s; add[r][c] += s; add[r + l][c] -= s; cut[r][c + 1] += s; cut[r + l][c + l + 1] -= s; } Rep(j, 1, n) { Rep(i, 1, n) add[i][j] += add[i - 1][j]; } Rep(i, 1, n) { Rep(j, 1, n) cut[i][j] += cut[i - 1][j - 1]; } Rep(i, 1, n) { Rep(j, 1, n) A[i][j] += A[i][j - 1] + add[i][j] - cut[i][j]; } LL Answer = 0; Rep(i, 1, n) Rep(j, 1, n) Answer ^= A[i][j]; cout << Answer; return 0; }

Problem 3 二維差分