Description:
求
∑infx=0∑r1i=l1a[i]==x∑r2j=l2a[j]==x
∑
x
=
0
i
n
f
∑
i
=
l
1
r
1
a
[
i
]
==
x
∑
j
=
l
2
r
2
a
[
j
]
==
x
Solution:
把询问拆成四个
(l1−1,l2−1),(l1−1,r2),(r1,l2−1)(r1,r2)
(
l
1
−
1
,
l
2
−
1
)
,
(
l
1
−
1
,
r
2
)
,
(
r
1
,
l
2
−
1
)
(
r
1
,
r
2
)
然后就可以莫队了。这里的莫队和普通的不太一样,因为涉及到两种统计。
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n, m, tot;
int a[N], cnt1[N], cnt2[N], bel[N];
long long ans[N];
struct que {
int l, r, f, id;
que() {}
que(int _l, int _r, int _f, int _id) : l(_l), r(_r), f(_f), id(_id) {}
bool friend operator < (const que &a, const que &b) {
return bel[a.l] == bel[b.l] ? a.r < b.r : bel[a.l] < bel[b.l];
}
} q[N];
int main() {
scanf("%d", &n);
int b = sqrt(n);
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
bel[i] = (i - 1) / b + 1;
}
scanf("%d", &m);
for(int i = 1; i <= m; ++i) {
int l1, r1, l2, r2;
scanf("%d%d%d%d", &l1, &r1, &l2, &r2);
if(l1 > 1 && l2 > 1) {
q[++tot] = que(l1 - 1, l2 - 1, 1, i);
}
if(l1 > 1) {
q[++tot] = que(l1 - 1, r2, -1, i);
}
if(l2 > 1) {
q[++tot] = que(r1, l2 - 1, -1, i);
}
q[++tot] = que(r1, r2, 1, i);
}
sort(q + 1, q + tot + 1);
int l = 0, r = 0;
long long sum = 0;
for(int i = 1; i <= tot; ++i) {
while(l < q[i].l) {
++l;
++cnt1[a[l]];
sum += cnt2[a[l]];
}
while(r < q[i].r) {
++r;
sum += cnt1[a[r]];
++cnt2[a[r]];
}
while(l > q[i].l) {
--cnt1[a[l]];
sum -= cnt2[a[l]];
--l;
}
while(r > q[i].r) {
sum -= cnt1[a[r]];
--cnt2[a[r]];
--r;
}
ans[q[i].id] += (long long)q[i].f * sum;
}
for(int i = 1; i <= m; ++i) {
printf("%lld\n", ans[i]);
}
return 0;
}