Description
输入一个n*m的矩阵,矩阵的每一个元素都是一个整数,然后有q个询问,每次询问一个子矩阵的权值。矩阵的权值是这样定义的,对于一个整数x,如果它在该矩阵中出现了p次,那么它给该矩阵的权值就贡献p2。
Solution
由于出现 p p p次的元素的贡献是 p 2 p^2 p2,我们可以看做每一对相同的元素可以产生 1 1 1的贡献。
我们定一个
S
S
S,大概为
40
40
40。
对于出现次数大于
S
S
S的元素,由于这样的元素个数不多,直接暴力搞。
对于小于
S
S
S的元素,我们两两配对,由于要求在矩形范围内,有
4
4
4个限制,所以是个四维偏序问题,将第一维排序,剩下的用三维树状数组即可。
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
#define Rep(i, j) for (register int i = 0, i##_end_ = (j); i < i##_end_; ++ i)
#define For(i, j, k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define X first
#define Y second
#define PB(a) push_back(a)
#define MP(a, b) make_pair(a, b)
#define SZ(a) ((int)(a).size())
#define ALL(a) a.begin(), a.end()
#define INF (0x3f3f3f3f)
#define INF1 (2139062143)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define y1 wozenmezhemecaia
#define sqr(x) ((x) * (x))
template <typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }
inline int read() {
static int _, __; static char c_;
for (_ = 0, __ = 1, c_ = getchar(); c_ < '0' || c_ > '9'; c_ = getchar()) if (c_ == '-') __ = -1;
for ( ; c_ >= '0' && c_ <= '9'; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);
return _ * __;
}
//EOT
const int maxn = 233, maxm = 233 * 233, S = 35, sumc = maxm / S + 5, maxq = 201314;
int n, m, q, ls[maxm], lss, ans[maxq], ty[maxm], cnt[maxm], a[maxn][maxn];
struct Query {
int x1, y1, x2, y2;
}qry[maxq];
namespace FuckYouAll {
int lss, ls[maxm], sum[maxn][maxn];
inline void Main() {
For(k, 1, lss) {
For(i, 1, n) For(j, 1, m)
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + (a[i][j] == ls[k]);
For(p, 1, q) {
ans[p] += sqr(sum[qry[p].x2][qry[p].y2] + sum[qry[p].x1 - 1][qry[p].y1 - 1]
- sum[qry[p].x1 - 1][qry[p].y2] - sum[qry[p].x2][qry[p].y1 - 1]);
}
}
}
}
namespace LoveYouForever {
int lss, ls[maxn * maxn];
struct Point { int a, b, c, d, id; }p[S * maxm + maxq];
int ps;
inline bool cmp(Point A, Point B) {
if (A.a != B.a) return A.a < B.a;
if (A.b != B.b) return A.b < B.b;
if (A.c != B.c) return A.c < B.c;
if (A.d != B.d) return A.d < B.d;
return A.id < B.id;
}
struct BIT {
int c[maxn][maxn][maxn];
#define lb(x) ((x) & -(x))
inline void update(int x, int y, int z) {
for (int i = x; i <= m; i += lb(i))
for (int j = y; j <= n; j += lb(j))
for (int k = z; k <= m; k += lb(k))
++ c[i][j][k];
}
inline int query(int x, int y, int z) {
int ans = 0;
for (int i = x; i; i -= lb(i))
for (int j = y; j; j -= lb(j))
for (int k = z; k; k -= lb(k))
ans += c[i][j][k];
return ans;
}
}bit;
vector<PII> vct[maxm];
inline void Main() {
For(i, 1, n) For(j, 1, m) if (ty[a[i][j]] == 2)
vct[lower_bound(ls + 1, ls + 1 + lss, a[i][j]) - ls].push_back(MP(i, j));
For(i, 1, lss) {
Rep(j, SZ(vct[i])) Rep(k, SZ(vct[i])) {
int x1 = vct[i][j].X, y1 = vct[i][j].Y, x2 = vct[i][k].X, y2 = vct[i][k].Y;
if (x1 > x2) swap(x1, x2);
if (y1 > y2) swap(y1, y2);
p[++ ps] = (Point){n - x1 + 1, m - y1 + 1, x2, y2, 0};
}
}
For(i, 1, q)
p[++ ps] = (Point){n - qry[i].x1 + 1, m - qry[i].y1 + 1, qry[i].x2, qry[i].y2, i};
sort(p + 1, p + 1 + ps, cmp);
//For(i, 1, ps) cout << p[i].a << ' ' << p[i].b << ' ' << p[i].c << ' ' << p[i].d << ' ' << p[i].id<< endl;
For(i, 1, ps)
if (!p[i].id) bit.update(p[i].b, p[i].c, p[i].d);
else ans[p[i].id] += bit.query(p[i].b, p[i].c, p[i].d);
}
}
int main()
{
#ifdef hany01
freopen("vegetable.in", "r", stdin);
freopen("vegetable.out", "w", stdout);
#endif
n = read(), m = read();
For(i, 1, n) For(j, 1, m) ls[(i - 1) * m + j] = a[i][j] = read();
sort(ls + 1, ls + 1 + n * m), lss = unique(ls + 1, ls + 1 + n * m) - ls - 1;
For(i, 1, n) For(j, 1, m) ++ cnt[a[i][j] = lower_bound(ls + 1, ls + 1 + lss, a[i][j]) - ls];
For(i, 1, lss)
if (cnt[i] > S) FuckYouAll::ls[++ FuckYouAll:: lss] = i, ty[i] = 1;
else LoveYouForever:: ls[++ LoveYouForever:: lss] = i, ty[i] = 2;
q = read();
For(i, 1, q) {
qry[i].x1 = read(), qry[i].y1 = read(), qry[i].x2 = read(), qry[i].y2 = read();
if (qry[i].x1 > qry[i].x2) swap(qry[i].x1, qry[i].x2);
if (qry[i].y1 > qry[i].y2) swap(qry[i].y1, qry[i].y2);
}
FuckYouAll:: Main();
LoveYouForever:: Main();
For(i, 1, q) printf("%d\n", ans[i]);
return 0;
}