[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]);
}