CF390E Inna and Large Sweet Matrix
CF390E Inna and Large Sweet Matrix
求 \(D - I\),用图像考虑的话,即为这样一个表格(求每个格对应矩阵和乘以格内标的数):
| \([1, y1)\) | \([y1, y2]\) | \((y2, m]\) | |
|---|---|---|---|
| \([1, x1)\) | -1 | 0 | -1 |
| \([x1, x2]\) | 0 | 1 | 0 |
| \((x2, n]\) | -1 | 0 | -1 |
加上矩阵总和之后:
| \([1, y1)\) | \([y1, y2]\) | \((y2, m]\) | |
|---|---|---|---|
| \([1, x1)\) | 0 | 1 | 0 |
| \([x1, x2]\) | 1 | 2 | 1 |
| \((x2, n]\) | 0 | 1 | 0 |
则计算答案的公式为:
\[D - I = \text{行区间和}([x_1, x_2]) + \text{列区间和}([y_1, y_2]) - total
\]
其中:
- 行区间和 \([x_1, x_2]\):第 \(x_1\) 到 \(x_2\) 行的每行糖果总数之和;
- 列区间和 \([y_1, y_2]\):第 \(y_1\) 到 \(y_2\) 列的每列糖果总数之和;
- \(total\):整个矩阵的糖果总数。
那么我们可以分别维护两个线段树:
- 每行的糖果总数(记为线段树 \(x\));
- 每列的糖果总数(记为线段树 \(y\))。
每次区间加操作时:
- 线段树 \(x\):对 \([x_1, x_2]\) 行,每行增加 \(v \times (y_2 - y_1 + 1)\) 颗糖果;
- 线段树 \(y\):对 \([y_1, y_2]\) 列,每列增加 \(v \times (x_2 - x_1 + 1)\) 颗糖果;
- 同时维护全局总数 \(total\)。
#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int MAXN = 4e6 + 9;
struct SEG {
struct Node {
int val, lazy;
Node() : val(0), lazy(0) {}
}t[MAXN << 2];
void push_down(int p, int l, int r) {
if(!t[p].lazy) return;
int mid = (l + r) >> 1;
t[p << 1].val += (mid - l + 1) * t[p].lazy;
t[p << 1].lazy += t[p].lazy;
t[(p << 1) + 1].val += (r - mid) * t[p].lazy;
t[(p << 1) + 1].lazy += t[p].lazy;
t[p].lazy = 0;
}
void push_up(int p) {
t[p].val = t[p << 1].val + t[(p << 1) + 1].val;
}
void update(int p, int l, int r, int nl, int nr, int v) {
if(nl <= l && r <= nr) {
t[p].val += (r - l + 1) * v;
t[p].lazy += v;
return;
}
push_down(p, l, r);
int mid = (l + r) >> 1;
if(nl <= mid) update(p << 1, l, mid, nl, nr, v);
if(nr > mid) update((p << 1) + 1, mid + 1, r, nl, nr, v);
push_up(p);
}
int query(int p, int l, int r, int nl, int nr) {
if(nl <= l && r <= nr) return t[p].val;
push_down(p, l, r);
int mid = (l + r) >> 1, rt = 0;
if(nl <= mid) rt += query(p << 1, l, mid, nl, nr);
if(nr > mid) rt += query((p << 1) + 1, mid + 1, r, nl, nr);
return rt;
}
void update(int n, int l, int r, int v) {update(1, 1, n, l, r, v);}
int query(int n, int l, int r) {return query(1, 1, n, l, r);}
}x, y;
int n, m, w, op, xx1, yy1, xx2, yy2, v, sum;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m >> w;
while(w--) {
cin >> op >> xx1 >> yy1 >> xx2 >> yy2;
if(!op) {
cin >> v;
x.update(n, xx1, xx2, (yy2 - yy1 + 1) * v);
y.update(m, yy1, yy2, (xx2 - xx1 + 1) * v);
sum += (xx2 - xx1 + 1) * (yy2 - yy1 + 1) * v;
}
else {
int ans = x.query(n, xx1, xx2) + y.query(m, yy1, yy2);
ans -= sum;
cout << ans << '\n';
}
}
return 0;
}

浙公网安备 33010602011771号