[CF703D] Mishka and Interesting sum

[CF703D] Mishka and Interesting sum - 离线处理,树状数组

Description

给定 (n) 个数的序列 (a)(m) 次操作。每次求 (a_l,a_{l+1},...,a_r) 中,出现偶数次的数的异或和。

Solution

即区间本质不同数的异或和与区间异或和的异或,关键是求区间本质不同数的异或和

考虑到 n 有 1e6,莫队跑不动了,考虑离线处理并用树状数组维护异或和,在每个数最后一次出现的地方放上这个数

#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;

struct Question
{
    int l, r, id;
    bool operator<(const Question &rhs) const
    {
        return l > rhs.l;
    }
};

struct BinaryIndexTree
{
    int n;
    int *a;

    BinaryIndexTree(int n) : n(n)
    {
        a = new int[n + 2];
        fill(a, a + n + 2, 0);
    }

    int lowbit(int x)
    {
        return x & (-x);
    }

    void add(int i, int x)
    {
        while (i <= n)
        {
            a[i] ^= x;
            i += lowbit(i);
        }
    }

    int sum(int i)
    {
        int ans = 0;
        while (i)
        {
            ans ^= a[i];
            i -= lowbit(i);
        }
        return ans;
    }
};

inline void read(int &x)
{
    int f = 1;
    x = 0;
    char s = getchar();
    while (!isdigit(s))
    {
        if (s == '-')
            f = -1;
        s = getchar();
    }
    while (isdigit(s))
    {
        x = x * 10 + s - '0';
        s = getchar();
    }
    x *= f;
}

signed main()
{
    int n, m;
    read(n);

    vector<int> a(n + 2);
    vector<int> prexor(n + 2);
    for (int i = 1; i <= n; i++)
        read(a[i]);
    for (int i = 1; i <= n; i++)
        prexor[i] = prexor[i - 1] ^ a[i];

    read(m);
    vector<int> ans(m + 2);
    vector<Question> questions(m + 2);
    for (int i = 1; i <= m; i++)
    {
        Question &question = questions[i];
        read(question.l);
        read(question.r);
        question.id = i;
        ans[i] = prexor[question.r] ^ prexor[question.l - 1];
    }

    vector<vector<Question>> asks(n + 2);
    for (int i = 1; i <= m; i++)
    {
        asks[questions[i].l].push_back(questions[i]);
    }

    BinaryIndexTree bit(n);
    map<int, int> last_pos;
    for (int i = n; i >= 1; i--)
    {
        int now = a[i];
        int &t = last_pos[now];
        if (t)
        {
            bit.add(t, now);
        }
        (t) = i;
        bit.add(i, now);
        for (const auto &question : asks[i])
        {
            ans[question.id] ^= bit.sum(question.r);
        }
    }

    for (int i = 1; i <= m; i++)
        printf("%d
", ans[i]);
}
原文地址:https://www.cnblogs.com/mollnn/p/14358625.html