需要支持操作:
- 在序列末尾添加数
- 给出
l
,
r
,
x
l,r,x
l,r,x 。
询问 [ l , r ] [l,r] [l,r] 中满足 a [ p ] ⊕ a [ p + 1 ] ⊕ ⋯ ⊕ a [ N ] ⊕ x a[p]\oplus a[p+1]\oplus\cdots\oplus a[N]\oplus x a[p]⊕a[p+1]⊕⋯⊕a[N]⊕x 最大的位置 p p p 以及这个异或和
对于 [ 1 , n ] [1,n] [1,n] 求使得 a [ p ] ⊕ ⋯ a [ n ] ⊕ x a[p]\oplus\cdots a[n]\oplus x a[p]⊕⋯a[n]⊕x 最大的 x x x 显然可以用 01trie 解决
变成求 p p p 也很简单,多开一棵 01trie 或者干脆用 bool 都可以解决
但是现在要求可以修改,还要求支持区间查询。
你可能发现异或和居然是往后到
N
N
N 的有点烦人
那么有没有办法让它跟“在序列末尾添加”一样?
有的,只需要用 维护 a[1~N] 的异或和 和 a[1~p-1] 的异或和 来代替就可以了。
接下来我们得到了一个简单的 01trie 问题
然而怎么支持区间查询呢?
根据已有的信息很容易联想到可持久化
至于最大值,只需要在 01trie insert 的时候一路向下标记谁最后来到这里即可。
输出异或和最大值而非 p
变量名起清楚一些,不至于把 MAXN 和 MXXN 搞混
注意递归边界……本质上是往下一层的时候要想清楚
一开始直接用这一位的二进制去指导下一位怎么走了
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iomanip>
#include<set>
#include<vector>
#include<map>
#include<queue>
using namespace std;
const int MAXN = 6e5 + 10;
const int MXXN = MAXN << 5;
int n, m, Total = 0;
char ch;
int Root[MAXN];
int To[MXXN][2], LatestViewed[MXXN];
bool TempBit[30];
int TempBitTotal;
int InArrayXorSum = 0;
#define CanPass (To[PosRight][TempBit[XorPos]^1] && LatestViewed[To[PosRight][TempBit[XorPos]^1]] >= LeftPos)
void Insert(int Tms, int &Pos, int OldPos, int BitPos)
{
Pos = ++Total;
LatestViewed[Pos] = Tms;
if (BitPos == 25) return;
bool tmpbt = TempBit[BitPos+1];
To[Pos][tmpbt^1] = To[OldPos][tmpbt^1];
Insert(Tms, To[Pos][tmpbt], To[OldPos][tmpbt], BitPos+1);
}
int Query(int LeftPos, int PosRight, int XorPos, int XorAns)
{
if (XorPos == 26) return XorAns;
if (CanPass) return Query(LeftPos, To[PosRight][TempBit[XorPos]^1], XorPos + 1, XorAns ^ ((TempBit[XorPos]^1)<<(25-XorPos)));
return Query(LeftPos, To[PosRight][TempBit[XorPos]], XorPos + 1, XorAns ^ ((TempBit[XorPos])<<(25-XorPos)));
}
int main()
{
scanf("%d%d", &n, &m);
for (int a, TempInt, i = 1; i <= n; ++i)
{
scanf("%d", &a);
TempInt = InArrayXorSum; TempBitTotal = 25;
memset(TempBit, 0, sizeof(TempBit));
while(TempInt)
{
TempBit[TempBitTotal--] = TempInt & 1;
TempInt >>= 1;
}
Insert(i, Root[i], Root[i-1], 0);
InArrayXorSum ^= a;
}
for (int l, r, x, TempInt, i = 1; i <= m; ++i)
{
scanf(" %c ", &ch);
if (ch == 'A')
{
++n;
scanf("%d", &x);
TempInt = InArrayXorSum; TempBitTotal = 25;
memset(TempBit, 0, sizeof(TempBit));
while(TempInt)
{
TempBit[TempBitTotal--] = TempInt & 1;
TempInt >>= 1;
}
Insert(n, Root[n], Root[n-1], 0);
InArrayXorSum ^= x;
}
if (ch == 'Q')
{
scanf("%d%d%d", &l, &r, &x);
x ^= InArrayXorSum;
TempInt = x; TempBitTotal = 25;
memset(TempBit, 0, sizeof(TempBit));
while(TempInt)
{
TempBit[TempBitTotal--] = TempInt & 1;
TempInt >>= 1;
}
printf("%d\n", Query(l, Root[r], 1, x));
}
}
return 0;
}