[SOJ475]【SPC #2】美丽的序列 ~ Beautiful Sequence【莫队】【哈希】

题意简述:给一个长度为\(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;
}

猜你喜欢

转载自www.cnblogs.com/suwakow/p/11680264.html