题目:BZOJ2741.
题目大意:给定一个长度为
n
n
n的序列
a
a
a,并有
M
M
M组询问
l
,
r
l,r
l,r,表示询问当
l
≤
i
≤
j
≤
r
l \leq i\leq j \leq r
l≤i≤j≤r时,
a
[
i
]
 
x
o
r
 
a
[
i
+
1
]
 
x
o
r
 
.
.
.
 
x
o
r
 
a
[
j
]
a[i]\,xor\,a[i+1]\,xor\,...\,xor\,a[j]
a[i]xora[i+1]xor...xora[j]的最大值.
1
≤
n
≤
1.2
∗
1
0
4
,
1
≤
m
≤
6000
1\leq n\leq 1.2*10^4,1\leq m\leq 6000
1≤n≤1.2∗104,1≤m≤6000.
回忆这种题的套路,我们发现这道题绝对要前缀xor一下,变成查询两个数的xor和最大.又由于是查询区间,所以上个可持久化0-1 Trie.一看两个端点都不确定,那就考虑一个朴素的暴力,暴力枚举一个端点,然后找另一个端点…时间复杂度 O ( 31 m n ) O(31mn) O(31mn)完美TLE(虽然我没试过)…
考虑如何优化,很容易想到万能分块.设每个块大小为siz,分成 n s i z \frac{n}{siz} sizn个块,预处理出第i个块到第j个块之间的答案f[i][j],然后暴力搞边上的块.预处理时间复杂度 O ( 31 n n s i z ) O(31n\frac{n}{siz}) O(31nsizn),总查询时间复杂度 O ( 31 m ∗ s i z ) O(31m*siz) O(31m∗siz),平衡一下取 s i z = n m siz=\frac{n}{\sqrt{m}} siz=mn可以做到 O ( 31 n m ) O(31n\sqrt{m}) O(31nm).
代码如下(没怎么写过分块比较丑请见谅QAQ):
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=12000,B=500,C=31;
struct Trie{
int s[2],cnt;
}tr[N*(C+2)+9]; //一定不能只开N*C的数组,因为可持久化Trie数的节点个数为N*(C+2),这是由于总共C+1位,可持久化Trie还要多建几个N个根
int cn,cr,rot[N+9];
void Trie_build(){cr=cn=0;}
void Trie_insert(int a){
rot[++cr]=++cn;
int x=rot[cr],x0=rot[cr-1];
for (int i=C;i>=0;--i){
tr[x]=tr[x0];++tr[x].cnt;
tr[x].s[a>>i&1]=++cn;x=cn;
x0=tr[x0].s[a>>i&1];
}
tr[x]=tr[x0];++tr[x].cnt;
}
int Trie_query(int l,int r,int a){
int xl=rot[l-1],xr=rot[r],ans=0,t;
for (int i=C;i>=0;--i){
t=a>>i&1;
if (tr[tr[xr].s[t^1]].cnt-tr[tr[xl].s[t^1]].cnt>0)
ans|=1<<i,xl=tr[xl].s[t^1],xr=tr[xr].s[t^1];
else xl=tr[xl].s[t],xr=tr[xr].s[t];
}
return ans;
}
int n,m,s[N+9],mod;
struct Block{
int l,r;
}bl[B+9];
int siz,cb,f[B+9][B+9],bel[N+9];
void Block_build(){
siz=n/sqrt(m);
if (n/siz>B) siz=n/B; //防止块数太多导致溢出
for (bl[cb=0].r=0;bl[cb].r<n;++cb) bl[cb+1].l=bl[cb].r+1,bl[cb+1].r=bl[cb].r+siz;
bl[cb].r=n;
for (int i=1;i<=n;++i)
bel[i]=bl[bel[i-1]].r<i?bel[i-1]+1:bel[i-1];
for (int i=1;i<=cb;++i)
for (int j=i;j<=cb;++j){
f[i][j]=f[i][j-1];
for (int k=bl[j].l;k<=bl[j].r;++k)
f[i][j]=max(f[i][j],Trie_query(bl[i].l,bl[j].r,s[k]));
}
}
int Block_query(int l,int r){
int ans=0,lb=bel[l],rb=bel[r];
if (lb+1>=rb){
for (int i=l;i<=r;++i)
ans=max(ans,Trie_query(l,r,s[i]));
return ans;
}
for (int i=l;i<=bl[lb].r;++i)
ans=max(ans,Trie_query(l,r,s[i]));
for (int i=bl[rb].l;i<=r;++i)
ans=max(ans,Trie_query(l,r,s[i]));
return max(ans,f[lb+1][rb-1]);
}
Abigail into(){
scanf("%d%d",&n,&m);
mod=n;++n;
for (int i=2;i<=n;++i){
scanf("%d",&s[i]);
s[i]^=s[i-1];
}
}
Abigail work(){
Trie_build();
for (int i=1;i<=n;++i)
Trie_insert(s[i]);
Block_build();
}
Abigail getans(){
int x,y,ans=0,l,r;
for (int i=1;i<=m;++i){
scanf("%d%d",&x,&y);
l=min(((LL)x+ans)%mod+1,((LL)y+ans)%mod+1);
r=max(((LL)x+ans)%mod+1,((LL)y+ans)%mod+1);
printf("%d\n",ans=Block_query(l,r+1));
}
}
int main(){
into();
work();
getans();
return 0;
}