P4024 题解
DS + 提交答案,还真有人出过这种题啊。
题目大意
给出一个带权二维矩阵
算法 \bf 1
设
首先有个显然的暴力:离散化后,莫队扫
时间复杂度为
我们发现这个算法能在每个点
算法 \bf 2
观察测试点
设每次询问的子矩形宽
算法 \bf 3
观察测试点
和算法
代码参考
算法
const int N = 1e6 + 9;
const int M = 6;
const int sz = 200;
int n, m, q, a[M][N];
ll res[M][M], Ans[N];
struct Bit {
int a[N];
inline void Add(int p, int x) {
while (p < N) a[p] += x, p += lb(p);
}
inline int Ask(int p) {
int res = 0;
while (p) res += a[p], p -= lb(p);
return res;
}
} bit[M];
struct Query {
int l, r, L, R, id;
inline bool operator<(const Query &x) const {
return l / sz == x.l / sz ? (r == x.r ? 0 : ((l / sz) & 1) ^ (r < x.r)) : l < x.l;
}
} Q[N];
inline void AddL(int x) {
re (i, m)
bit[i].Add(a[i][x], 1);
re (i, m) {
rep (j, i, m)
res[i][j] += bit[j].Ask(a[i][x] - 1);
}
}
inline void AddR(int x) {
re (i, m)
bit[i].Add(a[i][x], 1);
re (i, m) {
rep (j, 1, i)
res[j][i] += bit[j].Ask(N - 1) - bit[j].Ask(a[i][x]);
}
}
inline void DelL(int x) {
re (i, m) {
rep (j, i, m)
res[i][j] -= bit[j].Ask(a[i][x] - 1);
}
re (i, m)
bit[i].Add(a[i][x], -1);
}
inline void DelR(int x) {
re (i, m) {
rep (j, 1, i)
res[j][i] -= bit[j].Ask(N - 1) - bit[j].Ask(a[i][x]);
}
re (i, m)
bit[i].Add(a[i][x], -1);
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> m >> n >> q;
vector<int> vec;
if (m < n) {
re (i, m)
re (j, n)
cin >> a[i][j], vec.push_back(a[i][j]);
re (i, q)
cin >> Q[i].L >> Q[i].l >> Q[i].R >> Q[i].r, Q[i].id = i;
} else {
re (i, m)
re (j, n)
cin >> a[j][i], vec.push_back(a[j][i]);
re (i, q)
cin >> Q[i].l >> Q[i].L >> Q[i].r >> Q[i].R, Q[i].id = i;
swap(n, m);
}
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(), vec.end()), vec.end());
re (i, m)
re (j, n)
a[i][j] = lower_bound(vec.begin(), vec.end(), a[i][j]) - vec.begin() + 1;
sort(Q + 1, Q + q + 1);
int l = 1, r = 0;
re (i, q) {
if (i % 10000 == 0) dbg(i);
while (l > Q[i].l) AddL(--l);
while (r < Q[i].r) AddR(++r);
while (l < Q[i].l) DelL(l++);
while (r > Q[i].r) DelR(r--);
rep (j, Q[i].L, Q[i].R)
rep (k, j, Q[i].R)
Ans[Q[i].id] += res[j][k];
}
re (i, q)
cout << Ans[i] << '\n';
return 0;
}