前言
边界条件,烦人!(╯‵□′)╯︵┻━┻
题目
一句话题意:区间询问子区间异或和最大值。
讲解
其实做法很简单,将 (a_i) 做一个前缀异或和,然后分块+可持久化Trie就行了。
但是我们注意这样一个问题:如果我们要表示一个区间 ([l,r]) 的异或和,我们需要用 (a_{l-1}oplus a_{r}),对应到Trie上,(l-1) 是要被包含的,所以我们传的两个根应该是 (rt_{l-2},rt_r)。
显然会有越界的问题,我最开始想的是在前面放个 (0),但是这样写很麻烦。而且我没调出来
但其实这种边界用 (a_{l-1}) 问 ([l,r]) 即可。
代码
//12252024832524
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define TT template<typename T>
using namespace std;
typedef long long LL;
const int MAXN = 12005;
const int MAXB = 150;
int n,m,B,ans;
int a[MAXN];
LL Read()
{
LL x = 0,f = 1;char c = getchar();
while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
return x * f;
}
TT void Put1(T x)
{
if(x > 9) Put1(x/10);
putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
if(x < 0) putchar('-'),x = -x;
Put1(x); if(c >= 0) putchar(c);
}
TT T Max(T x,T y){return x > y ? x : y;}
TT T Min(T x,T y){return x < y ? x : y;}
TT T Abs(T x){return x < 0 ? -x : x;}
int ID(int x){return (x-1)/B;}
int FI[MAXN];
int tot,rt[MAXN];
struct Trie
{
int ch[2],cnt;
}t[MAXN * 32];
int newnode(){++tot;t[tot].ch[0] = t[tot].ch[1] = t[tot].cnt = 0;return tot;}
void Add(int lst,int &x,int val,int rk)
{
if(!x || x == lst) x = newnode(),t[x] = t[lst];
++t[x].cnt;
if(rk < 0) return;
bool to = val >> rk & 1;
Add(t[lst].ch[to],t[x].ch[to],val,rk-1);
}
int Query(int lst,int x,int val,int rk,int s)
{
if(rk < 0) return s;
bool to = (val >> rk & 1) ^ 1;
if(t[t[x].ch[to]].cnt-t[t[lst].ch[to]].cnt) return Query(t[lst].ch[to],t[x].ch[to],val,rk-1,s|(1<<rk));
else return Query(t[lst].ch[to^1],t[x].ch[to^1],val,rk-1,s);
}
int MAX[MAXB][MAXB];
int main()
{
// freopen("data.in","r",stdin);
// freopen("mine.out","w",stdout);
n = Read(); m = Read();
for(int i = 1;i <= n;++ i) Add(rt[i-1],rt[i],a[i] = a[i-1]^Read(),30);
B = ceil(sqrt(1.0*n*n/m/2));
for(int i = 1;i <= n;i += B)
{
int now = 0;
FI[ID(i)] = i;
for(int j = i;j <= n;++ j)
{
now = Max(now,Query(rt[i-1],rt[j-1],a[j],30,0));
now = Max(now,a[j]^a[i-1]);
if((ID(j)^ID(j+1)) || j == n) MAX[ID(i)][ID(j)] = now;
}
}
while(m --> 0)
{
int x = Read(),y = Read();
int L = (x+0ll+ans)%n+1,R = (y+0ll+ans)%n+1;
int l = Min(L,R),r = Max(L,R);
if(ID(l)+1 >= ID(r))
{
ans = Query(rt[l-1],rt[r],a[l-1],30,0);
for(int i = l;i <= r;++ i) ans = Max(ans,Query(rt[l-1],rt[i-1],a[i],30,0));
Put(ans,'
');
}
else
{
L = ID(l)+1,R = ID(r)-1;
ans = MAX[L][R];
L = FI[L];
ans = Max(ans,Query(rt[l-1],rt[r],a[l-1],30,0));
for(int i = l;i < L;++ i) ans = Max(ans,Query(rt[l-1],rt[r],a[i],30,0));
for(int i = FI[ID(r)];i <= r;++ i) ans = Max(ans,Query(rt[l-1],rt[i],a[i],30,0));
Put(ans,'
');
}
}
return 0;
}