题意简述:给一个长度为\(n\)的序列,每次给出\(x, y\),求有多少区间\([l, r]\)满足\(x\leq l\leq r\leq y\),且\([l, r]\)中每个元素都出现了偶数次。\(1\leq n, q \leq 10^5, 1\leq a_i\leq 10^6\)。
设\(s_{i, j}\in[0, 1]\)表示前\(i\)个位置中,元素\(j\)出现的总次数\(\bmod 2\)的结果。显然\([l, r]\)中每个元素都出现了偶数次等价于\(\forall i\in [1, \max a] s_{l-1, i}=s_{r, i}\)。因此对每个\(s_{i}\)进行哈希,原问题就变成了区间元素出现个数平方和,也就是一道莫队入门题。
#include <bits/stdc++.h>
#define R register
#define ll long long
#define mp make_pair
#define pll pair<ll, ll>
using namespace std;
const int N = 110000, M = 1100000;
const ll mod[2] = {1e9 + 7, 1e9 + 9}, base[2] = {19260817, 19660813};
int n, q, B, bel[N], a[N], app[M], num, cnt, b[N], times[N];
ll pw[M][2], hs[N][2], sum, ans[N];
struct node {
int x, y, ind;
node (int x = 0, int y = 0, int i = 0) : x(x), y(y), ind(i) {}
inline bool operator < (const node &a) const {
if (bel[x] == bel[a.x])
return (bel[x] & 1) ? y < a.y : y > a.y;
return bel[x] < bel[a.x];
}
}que[N];
map<pll, int> tab;
template <class T> inline void read(T &x) {
x = 0;
char ch = getchar(), w = 0;
while (!isdigit(ch)) w = (ch == '-'), ch = getchar();
while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
x = w ? -x : x;
return;
}
inline void add(int p) {
sum += times[b[p]], ++times[b[p]];
return;
}
inline void del(int p) {
--times[b[p]], sum -= times[b[p]];
return;
}
int main() {
int x, y;
read(n);
int maxA = 0;
for (R int i = 1; i <= n; ++i)
read(a[i]), maxA = max(maxA, a[i]);
pw[0][0] = pw[0][1] = 1;
for (R int i = 1; i <= maxA; ++i)
pw[i][0] = pw[i - 1][0] * base[0] % mod[0], pw[i][1] = pw[i - 1][1] * base[1] % mod[1];
tab[mp(0, 0)] = cnt = 1;
for (R int i = 1; i <= n; ++i) {
if (app[a[i]]) {
hs[i][0] = (hs[i - 1][0] + mod[0] - pw[a[i]][0]) % mod[0];
hs[i][1] = (hs[i - 1][1] + mod[1] - pw[a[i]][1]) % mod[1];
}
else {
hs[i][0] = (hs[i - 1][0] + pw[a[i]][0]) % mod[0];
hs[i][1] = (hs[i - 1][1] + pw[a[i]][1]) % mod[1];
}
app[a[i]] ^= 1;
pll now = mp(hs[i][0], hs[i][1]);
if (tab.find(now) == tab.end())
tab[now] = ++cnt;
b[i] = tab[now];
}
read(q);
B = max(1, (int) (n / sqrt(q)));
for (R int i = 0; i < n; ++i)
bel[i + 1] = i / B + 1;
for (R int i = 1; i <= q; ++i)
read(x), read(y), que[++num] = node(x - 1, y, i);
sort(que + 1, que + 1 + q);
int p1 = 0, p2 = 0;
times[1] = b[0] = 1;
for (R int i = 1; i <= q; ++i) {
while (p2 < que[i].y) add(++p2);
while (p1 > que[i].x) add(--p1);
while (p1 < que[i].x) del(p1++);
while (p2 > que[i].y) del(p2--);
ans[que[i].ind] = sum;
}
for (R int i = 1; i <= q; ++i)
printf("%lld\n", ans[i]);
return 0;
}
原文地址:https://www.cnblogs.com/suwakow/p/11680264.html
时间: 2024-10-20 18:31:51