题意是求 【a,b】 中 的最大字段异或和。 。
看了神牛题解才会的。
首先将 区间 转化成 前项和 中两个的异或值。
也就是 将 1- n 个数a[ ],转化成 0-n 个数的数列b[ ]。
也就是
b[ r ] ^ a[ l ] = a[l+1] ^ a[l+2]^...^a[ r ]
b[2] ^ b[ 0 ] = a[1 ]^a[ 2 ]
在查询 【l,r】 转化成 b【】上的 【l-1, r】上的查询。(没处理好 ,一直在b【】 上 查询【l,r】 ,wa 成狗了。。)
于是此题问 就转化成了 在 在区间查询 两个点最大异或值。
对于一个点,查询是 【l,r】 是 复杂度 是 O(nlgm) : m 是 数列中最大值 lgm 是其位数。
所以求区间 任取两个点的最大异或值 ,lgn 应该没有解法。
于是参考神牛的解法, 分块,维护每一块的块头那个点 和其后边的每一个点 代表的区间中的最大值,
每一块块头部点 共有sqrt(n) 个,
f[ i ][j] = max(f[i][j-1],query(idx[i],j)); 第i块到 j的位置的最大值。
预处理的复杂度 O(nsqrt(n)*lgm)
查询时 暴力 第一块。 第二块的开头到 r 已经预处理出来了。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <cstring>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <assert.h>
#include <queue>
#define REP(i,n) for(int i=0;i<n;i++)
#define TR(i,x) for(typeof(x.begin()) i=x.begin();i!=x.end();i++)
#define ALLL(x) x.begin(),x.end()
#define SORT(x) sort(ALLL(x))
#define CLEAR(x) memset(x,0,sizeof(x))
#define FILLL(x,c) memset(x,c,sizeof(x))
using namespace std;
const double eps = 1e-9;
#define LL long long
#define pb push_back
const int maxn = 31000;
const int T = 130;
int dp[100][maxn];
int a[maxn];
int b[maxn];
struct Node{
Node *s[2];
int sum;
}nodes[maxn*300];
Node *root[maxn],*null;
int C;
int n,m;
void init(){
C=0;
root[0] = null = &nodes[C++];
null->s[0] = null->s[1] = null;
null->sum = 0;
}
Node *insert(int v,int d,Node *root){
Node *rt = &nodes[C++];
rt->s[0] = root->s[0];
rt->s[1] = root->s[1];
rt->sum = root->sum+1;
if(d<0)return rt;
int p = (v>>d)&1;
rt->s[p] = insert(v,d-1,root->s[p]);
return rt;
}
int query(int v,int d,Node *rt1,Node *rt2){
if(d<0)return 0;
int p = (v>>d)&1;
if(rt2->s[p^1]->sum - rt1->s[p^1]->sum){
return (1<<d)+query(v,d-1,rt1->s[p^1],rt2->s[p^1]);
}
return query(v,d-1,rt1->s[p],rt2->s[p]);
}
const int K = 31;
void solve(){
init();
CLEAR(dp);
for(int i=0;i<=n;i++){
root[i+1] = insert(b[i],K,root[i]);
}
}
int get_ans(int l,int r){
int ans = 0;
l--;
int l_id = l/T+1;
int r_id = r/T+1;
if(r_id > l_id){
ans = dp[l_id+1][r];
}
for(int i=l;i<=min(r,(l_id+1)*T);i++){
ans = max(ans,query(b[i],K,root[l],root[r+1]));
}
return ans;
}
void solve1(){
int lastans = 0 ;
for(int i=1;i<=m;i++){
int l,r,x,y;
scanf("%d%d",&x,&y);
l = min(((x+lastans%n)%n)+1,((y+lastans%n)%n)+1);
r = max(((x+lastans%n)%n)+1,((y+lastans%n)%n)+1);
int ans = get_ans(l,r);
printf("%d\n",ans);
lastans = ans;
}
}
int main(){
scanf("%d%d",&n,&m);
CLEAR(b);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[i] = b[i-1]^a[i];
}
solve();
for(int i=1;i<=n;i++){
int idx = i/T+1;
for(int j=1;j<=idx;j++){
int l_idx =(j-1)*T;
dp[j][i] = max(dp[j][i-1],query(b[i],K,root[l_idx],root[i+1]));
}
}
solve1();
return 0;
}