P4024 [CTSC2012]统计学家
P4024 [CTSC2012]统计学家
Solution
首先考虑离散化。
rev1 & rev2
发现要么 \(n = 1\),要么 \(m = 1\),相当于对于一个一维数列求区间逆序对数。
由于没有修改操作,考虑将查询离线,离线完了考虑莫队,移动的时候在树状数组上修改即可。
具体地,当左端点向左移动到 \(i\) 时,在树状数组上查询 \(< a_i\) 的数的个数,累加到答案,并将 \(a_i\) 加入树状数组。
当右端点向右移动到 \(i\) 时,在树状数组上查询 \(> a_i\) 的数的个数,累加到答案,并将 \(a_i\) 加入到树状数组。
删除操作同理。要注意加入和删除在对于更新答案和更新树状数组时的顺序。
rev3 & rev4 & rev5 & rev8 & rev9 & rev10
继承树状数组 + 莫队的想法,我们把这种做法拓展到二维。
具体地,对 \(n\) 行维护 \(n\) 个树状数组,对列进行离线莫队。
为方便统计答案,记 \(f[i][j]\) 表示第 \(i\) 行的元素 \(x\) 与第 \(y\) 列的元素之间贡献的答案。这里钦定 \(i < j\),那么需要统计 \(x > y\) 的对,且同时满足列的限制。
不难发现,每次查询的答案即为 \(\sum\limits_{i = 1}^{n}\sum\limits_{j = i}^{n}f_{i, j}\)。
同样地,在加入和删除 一列 元素时,对左端点和右端点分别讨论。
具体地,当左端点向左移动到 \(x\) 时,答案累加 \(\sum\limits_{i = 1}^{n}\sum\limits_{j = i}^{n}\sum\limits_{k}a_{k}<a_{i, x}\),在树状数组上加入 $\forall 1 \le i\le n, a_{i, x} $。
当右端点向右移动到 \(x\) 时,答案累加 \(\sum\limits_{i = 1}^{n}\sum\limits_{j = 1}^{i}\sum\limits_{k}a_{k} > a_{i, x}\),在树状数组上加入 \(\forall 1 \le i \le n, a_{i, x}\)。
这样的思想还是挺有趣的:对全局修改树状数组,统计时自行根据限制限定查询范围。
设 \(m\) 与 \(Q\) 同级,时间复杂度为 \(O(m\sqrt{m}n^2\log{(nm)} + mn^2)\)。空间上用 vector
优化。
若 \(n > m\),把矩阵翻一下然后交换 \(m, n\) 即可。
挂一下某些数据点的大致运行效率。
rev3: rev4: rev5:
rev8: rev9:
最慢的跑了 \(4min\)。可以接受。
rev10
这里我们先缓一下,引出另一个解决这道题的方法:二维前缀和。
观察数据点 10,发现 \(n, m\) 只有 \(80\),不妨直接记 \(ans[i][j][x][y]\) 表示 \((i, j)\) 到 \((x, y)\) 内的答案。
采用 \(O(n^2m^2)\) 预处理一下即可。
具体地,可以引入另一个四维数组 \(s[i][j][x][y]\),表示 \((i, j)\) 到 \((x, y)\) 内 \(> a_{x, y}\) 的数的数量,四重循环两次,一次倒着预处理 \(s\),一次正着预处理 \(ans\)。
以上的 \((i, j)\) 和 \((x, y)\) 均满足 \(i \le x\) 且 $ j \le y$。
rev6
数据点 6 和数据点 7 都是 \(n , m = 1000\),这意味着级别飙升到 \(10^9\),而且还要带个 \(\log\)。
我们试图用树状数组 + 莫队跑一下数据点 6:
每 \(10s\) 只能处理几十个询问,效率不尽人意。
仔细观察数据点 6,发现矩阵的值居然有递减关系!
这说明所有满足坐标限制的点对都可以贡献到答案中。
二维前缀和预处理一下,很简单。当然每次 \(O(1)\) 直接算好像也可以。
rev7
发现矩阵中只有 \(5\) 和 \(9\) 两种值,那么也是预处理乱搞一下即可(因为答案只与矩阵边长和两个角的值有关,与坐标无关)。
我的做法是根据左上角和右下角的值分 \(4\) 种情况讨论,分别记 \(ans1/ans2/ans3/ans4[x][y]\) 表示边长为 \(x, y\) 的矩阵对应四种情况的值。实际上讨论的时候,我还把每种情况分了两种情况讨论,具体来说是把 \(2 \times 2\) 的矩阵视作一个点来转移。
这个一定要画图分析才来的快。
给两个矩阵方便观察:
5 9 5 9 5 9 5 9 5 9
9 5 9 5 9 5 9 5 9 5
5 9 5 9 5 9 5 9 5 9
9 5 9 5 9 5 9 5 9 5
5 9 5 9 5 9 5 9 5 9
9 5 9 5 9 5 9 5 9 5
5 9 5 9 5 9 5 9 5 9
9 5 9 5 9 5 9 5 9 5
5 9 5 9 5 9 5 9 5 9
9 5 9 5 9 5 9 5 9 5
5 9 5 9 5 9 5 9 5 9
9 5 9 5 9 5 9 5 9 5
5 9 5 9 5 9 5 9 5 9
9 5 9 5 9 5 9 5 9 5
-
左上角为 \(5\),右下角为 \(5\):参见第一个矩阵,以 \((1, 1)\) 为左上角,\((i, j)\) 为右下角。
-
\(i \bmod 2 = 1, j \bmod 2 = 1\):
单独处理边界:\(ans1[1][x] = ans1[x][1] = \frac{x^2 - 1}{8}\)。
递推:\(ans1[i][j] = ans1[i - 2][j] + ans1[i][j - 2] - ans1[i - 2][j - 2] + \frac{(i - 1)(j - 1)}{2} + \frac{ij - 1}{2}\)。
-
\(i \bmod 2 = 0, j \bmod 2 = 0\):
不用单独处理边界。
递推:\(ans1[i][j] = ans1[i - 2][j] + ans1[i][j - 2] - ans1[i - 2][j - 2] + \frac{(i - 1)(j - 1) - 1}{2} + \frac{ij}{2}\)。
-
-
左上角为 \(5\),右下角为 \(9\):参见第一个矩阵,以 \((1, 1)\) 为左上角,\((i, j)\) 为右下角。
-
\(i \bmod 2 = 1, j \bmod 2 = 0\):
单独处理边界:\(ans2[1][x] = \frac{x^2 - 2x}{8}\)。
递推:\(ans2[i][j] = ans2[i - 2][j] + ans2[i][j - 2] - ans2[i - 2][j - 2] + \frac{i(j - 1) - 1}{2} + \frac{(i - 1)j}{2}\)。
-
\(i \bmod 2 = 0, j \bmod 2 = 1\):
单独处理边界:\(ans2[x][1] = \frac{x^2 - 2x}{8}\)。
递推:\(ans2[i][j] = ans2[i - 2][j] + ans2[i][j - 2] - ans2[i - 2][j - 2] + \frac{(i - 1)j - 1}{2} + \frac{i(j - 1)}{2}\)。
-
-
左上角为 \(9\),右下角为 \(5\):参见第二个矩阵,以 \((1, 1)\) 为左上角,\((i, j)\) 为右下角。
-
\(i \bmod 2 = 1, j \bmod 2 = 0\):
单独处理边界:\(ans3[1][x] = \frac{x^2 + 2x}{8}\)。
递推:\(ans3[i][j] = ans3[i - 2][j] + ans3[i][j - 2] - ans3[i - 2][j - 2] + \frac{(i - 1)(j - 1)}{2} + \frac{ij}{2}\)。
-
\(i \bmod 2 = 0, j \bmod 2 = 1\):
单独处理边界:\(ans3[x][1] = \frac{x^2 + 2x}{8}\)。
递推:\(ans3[i][j] = ans3[i - 2][j] + ans3[i][j - 2] - ans3[i - 2][j - 2] + \frac{(i - 1)(j - 1)}{2} + \frac{ij}{2}\)。
-
-
左上角为 \(9\),右下角为 \(9\):参见第二个矩阵,以 \((1, 1)\) 为左上角,\((i, j)\) 为右下角。
-
\(i \bmod 2 = 1, j \bmod 2 = 1\):
单独处理边界:\(ans4[1][x] = ans4[x][1] = \frac{x^2 - 1}{8}\)。
递推:\(ans4[i][j] = ans4[i - 2][j] + ans4[i][j - 2] - ans4[i - 2][j - 2] + \frac{i(j - 1)}{2} + \frac{(i - 1)j}{2}\)。
-
\(i \bmod 2 = 0, j \bmod 2 = 0\):
不用单独处理边界。
递推:\(ans4[i][j] = ans4[i - 2][j] + ans4[i][j - 2] - ans4[i - 2][j - 2] + \frac{i(j - 1)}{2} + \frac{(i - 1)j}{2}\)。
-
Final Code
#include<bits/stdc++.h>
#define lowbit(x) x & (-x)
#define LL long long
#define EB emplace_back
using namespace std;
int n, m, Q;
namespace Cleveland // rev1
{
const int N = 2e6 + 5;
const int M = sqrt(N) + 5;
LL ans[N], xorans = 0;
int a[N], tot = 0;
LL res = 0;
struct Shiranui
{
int v;
int bel;
}srn[N];
struct Akashi
{
int l, r, id;
}aks[N];
int svt, snncnt;
struct Shinano
{
int l, r;
}snn[M];
struct Taiho
{
int tr[N];
void add(int x, int v)
{
for(int i = x; i <= tot; i += lowbit(i))
tr[i] += v;
}
LL ask(int x)
{
LL res = 0;
for(int i = x; i; i -= lowbit(i))
res += tr[i];
return res;
}
}tho;
void MaddL(int x)
{
tho.add(srn[x].v, 1);
res += tho.ask(srn[x].v - 1);
}
void MaddR(int x)
{
tho.add(srn[x].v, 1);
res += tho.ask(tot) - tho.ask(srn[x].v);
}
void MdelL(int x)
{
res -= tho.ask(srn[x].v - 1);
tho.add(srn[x].v, -1);
}
void MdelR(int x)
{
res -= tho.ask(tot) - tho.ask(srn[x].v);
tho.add(srn[x].v, -1);
}
void solve()
{
cerr << "Cleveland" << endl;
svt = sqrt(m);
snncnt = m / svt;
for(int i = 1; i <= snncnt; ++i)
{
snn[i].l = snn[i - 1].r + 1;
snn[i].r = svt * i;
}
if(snn[snncnt].r < m)
{
snncnt++;
snn[snncnt].l = snn[snncnt - 1].r + 1;
snn[snncnt].r = m;
}
for(int i = 1; i <= snncnt; ++i)
for(int j = snn[i].l; j <= snn[i].r; ++j)
srn[j].bel = i;
for(int i = 1; i <= m; ++i)
{
scanf("%d", &srn[i].v);
a[i] = srn[i].v;
}
sort(a + 1, a + m + 1);
tot = unique(a + 1, a + m + 1) - (a + 1) + 1;
for(int i = 1; i <= m; ++i)
{
srn[i].v = lower_bound(a + 1, a + tot + 1, srn[i].v) - a + 1;
assert(srn[i].v > 0);
}
for(int i = 1; i <= Q; ++i)
{
int lx, ly, rx, ry;
scanf("%d %d %d %d", &lx, &ly, &rx, &ry);
aks[i].l = ly, aks[i].r = ry, aks[i].id = i;
}
sort(aks + 1, aks + Q + 1, [&](Akashi A, Akashi B){
if(srn[A.l].bel == srn[B.l].bel)
{
if(srn[A.l].bel & 1)
return A.r < B.r;
return A.r > B.r;
}
return srn[A.l].bel < srn[B.l].bel;
});
// cerr << "AVICII" << endl;
int L = 1, R = 0;
for(int i = 1; i <= Q; ++i)
{
// cerr << "Nagisa" << endl;
while(L > aks[i].l) MaddL(--L);
while(R < aks[i].r) MaddR(++R);
while(L < aks[i].l) MdelL(L++);
while(R > aks[i].r) MdelR(R--);
ans[aks[i].id] = res;
}
for(int i = 1; i <= Q; ++i)
xorans ^= ans[i];
printf("%lld\n", xorans);
}
}
namespace Helena // rev2
{
const int N = 2e6 + 5;
const int M = sqrt(N) + 5;
LL ans[N], xorans = 0;
int a[N], tot = 0;
LL res = 0;
struct Shiranui
{
int v;
int bel;
}srn[N];
struct Akashi
{
int l, r, id;
}aks[N];
int svt, snncnt;
struct Shinano
{
int l, r;
}snn[M];
struct Taiho
{
int tr[N];
void add(int x, int v)
{
for(int i = x; i <= tot; i += lowbit(i))
tr[i] += v;
}
LL ask(int x)
{
LL res = 0;
for(int i = x; i; i -= lowbit(i))
res += tr[i];
return res;
}
}tho;
void MaddL(int x)
{
tho.add(srn[x].v, 1);
res += tho.ask(srn[x].v - 1);
}
void MaddR(int x)
{
tho.add(srn[x].v, 1);
res += tho.ask(tot) - tho.ask(srn[x].v);
}
void MdelL(int x)
{
res -= tho.ask(srn[x].v - 1);
tho.add(srn[x].v, -1);
}
void MdelR(int x)
{
res -= tho.ask(tot) - tho.ask(srn[x].v);
tho.add(srn[x].v, -1);
}
void solve()
{
cerr << "Helena" << endl;
svt = sqrt(n);
snncnt = n / svt;
for(int i = 1; i <= snncnt; ++i)
{
snn[i].l = snn[i - 1].r + 1;
snn[i].r = svt * i;
}
if(snn[snncnt].r < n)
{
snncnt++;
snn[snncnt].l = snn[snncnt - 1].r + 1;
snn[snncnt].r = n;
}
for(int i = 1; i <= snncnt; ++i)
for(int j = snn[i].l; j <= snn[i].r; ++j)
srn[j].bel = i;
for(int i = 1; i <= n; ++i)
{
scanf("%d", &srn[i].v);
a[i] = srn[i].v;
}
sort(a + 1, a + n + 1);
tot = unique(a + 1, a + n + 1) - (a + 1) + 1;
for(int i = 1; i <= n; ++i)
srn[i].v = lower_bound(a + 1, a + tot + 1, srn[i].v) - a + 1;
for(int i = 1; i <= Q; ++i)
{
int lx, ly, rx, ry;
scanf("%d %d %d %d", &lx, &ly, &rx, &ry);
aks[i].l = lx, aks[i].r = rx, aks[i].id = i;
}
sort(aks + 1, aks + Q + 1, [&](Akashi A, Akashi B){
if(srn[A.l].bel == srn[B.l].bel)
{
if(srn[A.l].bel & 1)
return A.r < B.r;
return A.r > B.r;
}
return srn[A.l].bel < srn[B.l].bel;
});
int L = 1, R = 0;
for(int i = 1; i <= Q; ++i)
{
while(L > aks[i].l) MaddL(--L);
while(R < aks[i].r) MaddR(++R);
while(L < aks[i].l) MdelL(L++);
while(R > aks[i].r) MdelR(R--);
ans[aks[i].id] = res;
}
for(int i = 1; i <= Q; ++i)
xorans ^= ans[i];
printf("%lld\n", xorans);
}
}
namespace Enterprise // rev3, rev5
{
const int N = 2e6 + 5;
const int M = sqrt(N) + 5;
struct Shiranui
{
int bel;
}srn[N];
struct Akashi
{
int lx, ly, rx, ry;
int id;
}aks[N];
int svt, snncnt;
struct Shinano
{
int l, r;
}snn[M];
int tot = 0;
struct Taiho
{
vector<LL> tr;
void add(int x, int v)
{
// cerr << "add : pass" << endl;
for(int i = x; i <= tot; i += lowbit(i))
tr[i] += v;
}
LL ask(int x)
{
// cerr << "ask : pass" << " " << x << endl;
LL res = 0;
for(int i = x; i; i -= lowbit(i))
res += tr[i];
return res;
}
};
vector<Taiho> tho;
LL ans[N], xorans = 0;
vector<int> vec[N];
vector<int> a;
vector<LL> f[N];
void MaddL(int x)
{
// cerr << "MaddL : pass" << endl;
for(int i = 1; i <= n; ++i)
tho[i].add(vec[i][x], 1);
for(int i = 1; i <= n; ++i)
for(int j = i; j <= n; ++j)
f[i][j] += tho[j].ask(vec[i][x] - 1);
}
void MaddR(int x)
{
for(int i = 1; i <= n; ++i)
tho[i].add(vec[i][x], 1);
// cerr << "MaddR : pass" << endl;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= i; ++j)
f[j][i] += tho[j].ask(tot) - tho[j].ask(vec[i][x]);
}
void MdelL(int x)
{
// cerr << "MdelL : pass" << endl;
for(int i = 1; i <= n; ++i)
for(int j = i; j <= n; ++j)
f[i][j] -= tho[j].ask(vec[i][x] - 1);
for(int i = 1; i <= n; ++i)
tho[i].add(vec[i][x], -1);
}
void MdelR(int x)
{
// cerr << "MdelR : pass" << endl;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= i; ++j)
f[j][i] -= tho[j].ask(tot) - tho[j].ask(vec[i][x]);
for(int i = 1; i <= n; ++i)
tho[i].add(vec[i][x], -1);
}
void solve()
{
cerr << " Enterprise" << endl;
double st, ed;
st = clock();
svt = sqrt(m);
snncnt = m / svt;
for(int i = 1; i <= snncnt; ++i)
{
snn[i].l = snn[i - 1].r + 1;
snn[i].r = svt * i;
}
if(snn[snncnt].r < m)
{
snncnt++;
snn[snncnt].l = snn[snncnt - 1].r + 1;
snn[snncnt].r = m;
}
for(int i = 1; i <= snncnt; ++i)
for(int j = snn[i].l; j <= snn[i].r; ++j)
srn[j].bel = i;
tho.resize(n + 1);
for(int i = 1; i <= n; ++i)
{
vec[i].resize(m + 1);
f[i].resize(n + 1, 0);
}
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
{
scanf("%d", &vec[i][j]);
a.EB(vec[i][j]);
}
sort(a.begin(), a.end());
a.erase(unique(a.begin(), a.end()), a.end());
tot = (int)a.size() + 1;
for(int i = 1; i <= n; ++i)
tho[i].tr.resize(tot + 1);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
{
vec[i][j] = lower_bound(a.begin(), a.end(), vec[i][j]) - a.begin() + 2; // !!! + 1
assert(vec[i][j] > 0);
}
for(int i = 1; i <= Q; ++i)
{
scanf("%d %d %d %d", &aks[i].lx, &aks[i].ly, &aks[i].rx, &aks[i].ry);
aks[i].id = i;
}
sort(aks + 1, aks + Q + 1, [&](Akashi A, Akashi B){
if(srn[A.ly].bel == srn[B.ly].bel)
{
if(srn[A.ly].bel & 1)
return A.ry < B.ry;
return A.ry > B.ry;
}
return srn[A.ly].bel < srn[B.ly].bel;
});
// cerr << "AVICII" << endl;
int L = 1, R = 0;
ed = clock();
cerr << "preprocess : " << ed - st << endl;
st = clock();
double ST = st;
for(int i = 1; i <= Q; ++i)
{
// cerr << "Nagisa" << endl;
while(L > aks[i].ly) MaddL(--L);
while(R < aks[i].ry) MaddR(++R);
while(L < aks[i].ly) MdelL(L++);
while(R > aks[i].ry) MdelR(R--);
for(int j = aks[i].lx; j <= aks[i].rx; ++j)
for(int k = j; k <= aks[i].rx; ++k)
ans[aks[i].id] += f[j][k];
double ed = clock();
if(ed - st > 10000)
{
cerr << (ed - ST) / 1000 << " " << i << endl;
st = ed;
}
}
for(int i = 1; i <= Q; ++i)
xorans ^= ans[i];
printf("%lld\n", xorans);
}
}
namespace Yorktown // rev4, rev8, rev9
{
const int N = 2e6 + 5;
const int M = sqrt(N) + 5;
struct Shiranui
{
int bel;
}srn[N];
struct Akashi
{
int lx, ly, rx, ry;
int id;
}aks[N];
int svt, snncnt;
struct Shinano
{
int l, r;
}snn[M];
int tot = 0;
struct Taiho
{
vector<LL> tr;
void add(int x, int v)
{
// cerr << "add : pass" << endl;
for(int i = x; i <= tot; i += lowbit(i))
tr[i] += v;
}
LL ask(int x)
{
// cerr << "ask : pass" << " " << x << endl;
LL res = 0;
for(int i = x; i; i -= lowbit(i))
res += tr[i];
return res;
}
};
vector<Taiho> tho;
LL ans[N], xorans = 0;
vector<int> vec[N];
vector<int> a;
vector<LL> f[N];
void MaddL(int x)
{
// cerr << "MaddL : pass" << endl;
for(int i = 1; i <= m; ++i)
tho[i].add(vec[i][x], 1);
for(int i = 1; i <= m; ++i)
for(int j = i; j <= m; ++j)
f[i][j] += tho[j].ask(vec[i][x] - 1);
}
void MaddR(int x)
{
for(int i = 1; i <= m; ++i)
tho[i].add(vec[i][x], 1);
// cerr << "MaddR : pass" << endl;
for(int i = 1; i <= m; ++i)
for(int j = 1; j <= i; ++j)
f[j][i] += tho[j].ask(tot) - tho[j].ask(vec[i][x]);
}
void MdelL(int x)
{
// cerr << "MdelL : pass" << endl;
for(int i = 1; i <= m; ++i)
for(int j = i; j <= m; ++j)
f[i][j] -= tho[j].ask(vec[i][x] - 1);
for(int i = 1; i <= m; ++i)
tho[i].add(vec[i][x], -1);
}
void MdelR(int x)
{
// cerr << "MdelR : pass" << endl;
for(int i = 1; i <= m; ++i)
for(int j = 1; j <= i; ++j)
f[j][i] -= tho[j].ask(tot) - tho[j].ask(vec[i][x]);
for(int i = 1; i <= m; ++i)
tho[i].add(vec[i][x], -1);
}
void solve()
{
cerr << "Yorktown" << endl;
double st, ed;
st = clock();
svt = sqrt(n);
snncnt = n / svt;
for(int i = 1; i <= snncnt; ++i)
{
snn[i].l = snn[i - 1].r + 1;
snn[i].r = svt * i;
}
if(snn[snncnt].r < n)
{
snncnt++;
snn[snncnt].l = snn[snncnt - 1].r + 1;
snn[snncnt].r = n;
}
for(int i = 1; i <= snncnt; ++i)
for(int j = snn[i].l; j <= snn[i].r; ++j)
srn[j].bel = i;
tho.resize(m + 1);
for(int i = 1; i <= m; ++i)
{
vec[i].resize(n + 1);
f[i].resize(m + 1, 0);
}
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
{
scanf("%d", &vec[j][i]);
a.EB(vec[j][i]);
}
sort(a.begin(), a.end());
a.erase(unique(a.begin(), a.end()), a.end());
tot = (int)a.size() + 1;
for(int i = 1; i <= m; ++i)
tho[i].tr.resize(tot + 1);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
{
vec[j][i] = lower_bound(a.begin(), a.end(), vec[j][i]) - a.begin() + 2; // !!! + 1
assert(vec[j][i] > 0);
}
for(int i = 1; i <= Q; ++i)
{
scanf("%d %d %d %d", &aks[i].lx, &aks[i].ly, &aks[i].rx, &aks[i].ry);
aks[i].id = i;
}
sort(aks + 1, aks + Q + 1, [&](Akashi A, Akashi B){
if(srn[A.lx].bel == srn[B.lx].bel)
{
if(srn[A.lx].bel & 1)
return A.rx < B.rx;
return A.rx > B.rx;
}
return srn[A.lx].bel < srn[B.lx].bel;
});
// cerr << "AVICII" << endl;
int L = 1, R = 0;
ed = clock();
cerr << "preprocess : " << ed - st << endl;
st = clock();
double ST = st;
for(int i = 1; i <= Q; ++i)
{
// cerr << "Nagisa" << endl;
while(L > aks[i].lx) MaddL(--L);
while(R < aks[i].rx) MaddR(++R);
while(L < aks[i].lx) MdelL(L++);
while(R > aks[i].rx) MdelR(R--);
for(int j = aks[i].ly; j <= aks[i].ry; ++j)
for(int k = j; k <= aks[i].ry; ++k)
ans[aks[i].id] += f[j][k];
double ed = clock();
if(ed - st > 10000)
{
cerr << (ed - ST) / 1000 << " " << i << endl;
st = ed;
}
}
for(int i = 1; i <= Q; ++i)
xorans ^= ans[i];
printf("%lld\n", xorans);
}
}
namespace Santiago // rev10
{
int a[82][82];
int w[6405], tot;
LL ans[82][82][82][82], xorans = 0;
LL s[82][82][82][82];
// s[x][y][i][j] = s[x + 1][y][i][j] + s[x][y + 1][i][j] - s[x + 1][y + 1][i][j] + val(x, y, i, j)
// s[x][y][i][j] : (x, y) -> (i, j) 内与 (i, j) 形成逆序对的数量
void solve()
{
cerr << "Santiago" << endl;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
{
scanf("%d", &a[i][j]);
w[++tot] = a[i][j];
}
sort(w + 1, w + tot + 1);
tot = unique(w + 1, w + tot + 1) - w;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
a[i][j] = lower_bound(w + 1, w + tot + 1, a[i][j]) - w;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
{
for(int x = i; x >= 1; --x)
for(int y = j; y >= 1; --y)
{
s[x][y][i][j] = s[x + 1][y][i][j] + s[x][y + 1][i][j] - s[x + 1][y + 1][i][j] + (a[x][y] > a[i][j]);
}
}
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
{
ans[i][j][i][j] = 0;
for(int x = i + 1; x <= n; ++x)
ans[i][j][x][j] = ans[i][j][x - 1][j] + s[i][j][x][j];
for(int y = j + 1; y <= m; ++y)
ans[i][j][i][y] = ans[i][j][i][y - 1] + s[i][j][i][y];
for(int x = i + 1; x <= n; ++x)
for(int y = j + 1; y <= m; ++y)
ans[i][j][x][y] = ans[i][j][x - 1][y] + ans[i][j][x][y - 1] - ans[i][j][x - 1][y - 1] + s[i][j][x][y];
}
while(Q--)
{
int lx, ly, rx, ry;
scanf("%d %d %d %d", &lx, &ly, &rx, &ry);
xorans ^= ans[lx][ly][rx][ry];
}
printf("%lld\n", xorans);
}
}
namespace Vanguard // rev6, rev7
{
const int N = 1e3 + 5;
int a[N][N];
namespace Belfast // rev6
{
LL ans[N][N], xorans = 0;
void solve()
{
cerr << "Belfast" << endl;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
ans[i][j] = ans[i - 1][j] + ans[i][j - 1] - ans[i - 1][j - 1] + i * j - 1;
while(Q--)
{
int lx, ly, rx, ry;
scanf("%d %d %d %d", &lx, &ly, &rx, &ry);
xorans ^= ans[rx - lx + 1][ry - ly + 1];
}
printf("%lld\n", xorans);
}
}
namespace Illustrious // rev7
{
LL xorans = 0;
LL ans1[N][N], ans2[N][N], ans3[N][N], ans4[N][N];
void preprocess()
{
for(int i = 1; i < N; i += 2)
ans1[1][i] = ans1[i][1] = (i * i - 1) / 8;
for(int i = 3; i < N; i += 2)
for(int j = 3; j < N; j += 2)
ans1[i][j] = ans1[i - 2][j] + ans1[i][j - 2] - ans1[i - 2][j - 2] + (i - 1) * (j - 1) / 2 + (i * j - 1) / 2;
for(int i = 2; i < N; i += 2)
for(int j = 2; j < N; j += 2)
ans1[i][j] = ans1[i - 2][j] + ans1[i][j - 2] - ans1[i - 2][j - 2] + ((i - 1) * (j - 1) - 1) / 2 + i * j / 2;
for(int i = 2; i < N; i += 2)
ans2[1][i] = ans2[i][1] = i * (i - 2) / 8;
for(int i = 3; i < N; i += 2)
for(int j = 2; j < N; j += 2)
ans2[i][j] = ans2[i - 2][j] + ans2[i][j - 2] - ans2[i - 2][j - 2] + (i * (j - 1) - 1) / 2 + (i - 1) * j / 2;
for(int i = 2; i < N; i += 2)
for(int j = 3; j < N; j += 2)
ans2[i][j] = ans2[i - 2][j] + ans2[i][j - 2] - ans2[i - 2][j - 2] + ((i - 1) * j - 1) / 2 + i * (j - 1) / 2;
for(int i = 2; i < N; i += 2)
ans3[1][i] = ans3[i][1] = i * (i + 2) / 8;
for(int i = 3; i < N; i += 2)
for(int j = 2; j < N; j += 2)
ans3[i][j] = ans3[i - 2][j] + ans3[i][j - 2] - ans3[i - 2][j - 2] + (i - 1) * (j - 1) / 2 + i * j / 2;
for(int i = 2; i < N; i += 2)
for(int j = 3; j < N; j += 2)
ans3[i][j] = ans3[i - 2][j] + ans3[i][j - 2] - ans3[i - 2][j - 2] + (i - 1) * (j - 1) / 2 + i * j / 2;
for(int i = 1; i < N; i += 2)
ans4[1][i] = ans4[i][1] = (i * i - 1) / 8;
for(int i = 3; i < N; i += 2)
for(int j = 3; j < N; j += 2)
ans4[i][j] = ans4[i - 2][j] + ans4[i][j - 2] - ans4[i - 2][j - 2] + i * (j - 1) / 2 + (i - 1) * j / 2;
for(int i = 2; i < N; i += 2)
for(int j = 2; j < N; j += 2)
ans4[i][j] = ans4[i - 2][j] + ans4[i][j - 2] - ans4[i - 2][j - 2] + i * (j - 1) / 2 + (i - 1) * j / 2;
}
void solve()
{
cerr << "Illustrious" << endl;
preprocess();
while(Q--)
{
int lx, ly, rx, ry;
scanf("%d %d %d %d", &lx, &ly, &rx, &ry);
int x = rx - lx + 1, y = ry - ly + 1;
if(a[lx][ly] == 5 && a[rx][ry] == 5) xorans ^= ans1[x][y];
if(a[lx][ly] == 5 && a[rx][ry] == 9) xorans ^= ans2[x][y];
if(a[lx][ly] == 9 && a[rx][ry] == 5) xorans ^= ans3[x][y];
if(a[lx][ly] == 9 && a[rx][ry] == 9) xorans ^= ans4[x][y];
}
printf("%lld\n", xorans);
}
}
void solve()
{
cerr << "Vanguard" << endl;
int cnt5 = 0, cnt9 = 0;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
{
scanf("%d", &a[i][j]);
cnt5 += (a[i][j] == 5);
cnt9 += (a[i][j] == 9);
}
if(cnt5 + cnt9 == n * m)
Illustrious::solve();
else Belfast::solve();
}
}
int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
scanf("%d %d %d", &n, &m, &Q);
if(n == 80 && m == 80) Santiago::solve();
else if(n == 1) Cleveland::solve();
else if(m == 1) Helena::solve();
else
{
if(n == 1000 && m == 1000) Vanguard::solve();
else if(n < m) Enterprise::solve();
else Yorktown::solve();
}
return 0;
}