1 #include <iostream>
2 #include <cstdio>
3 #include <algorithm>
4 #include <cstring>
5 #include <vector>
6 #include <utility>
7 #include <iomanip>
8 #include <string>
9 #include <cmath>
10 #include <queue>
11 #include <assert.h>
12 #include <map>
13
14 const int N = 12000 + 10;
15 const int SIZE = 111;//块状链表的根号50000
16 const int M = 50000 + 5;
17 using namespace std;
18 typedef long long ll;
19 struct Node{
20 int val;//代表数量
21 int num;//代表值
22 Node *ch[2];
23 }mem[N * 31 * 10], *root[N];
24 int n, m;//n为数量,m为操作次数
25 struct BLOCK_LIST{//块状链表
26 int data[SIZE];
27 int size, next;
28 void init(){
29 size = 0;
30 memset(data, 0, sizeof(data));
31 next = -1;
32 }
33 }list[SIZE];
34 int tot = 0;//记录mem使用空间
35 int Max[SIZE + 10][SIZE + 10], Pos;//表示从i到j块的最大异或值
36 int data[N];
37
38 Node *NEW(){//创建新trie节点
39 Node *p = &mem[tot++];
40 p->val = p->num = 0;
41 p->ch[0] = p->ch[1] = NULL;
42 return p;
43 }
44 void insert(Node *&p, Node *&last, int x){//k为根
45 p = NEW();
46
47 Node *u = p, *a = last;
48 for (int i = 30; i >= 0 ; i--){
49 int t = (((1 << i) & x) == 0 ? 0 : 1);
50 if (u->ch[t] == NULL){
51 u->ch[t] = NEW();
52 u->ch[t]->val = t;
53 u->ch[t]->num = a->ch[t]->num + 1;
54 }
55 u->ch[t ^ 1] = a -> ch[t ^ 1];
56 u = u -> ch[t];
57 a = a -> ch[t];
58 }
59 return;
60 }
61 int find(Node *&a, Node *&b, int val){
62 int Ans = 0;
63 Node *x = a, *y = b;
64 for (int i = 30; i >= 0; i--){
65
66 int t = ((((1 << i) & val) == 0 ? 0 : 1) ^ 1);
67 if (x->ch[t] == NULL || (x->ch[t]->num - y->ch[t]->num) <= 0) t = (t ^ 1);
68 Ans += (1 << i) * t;
69 x = x->ch[t];
70 y = y->ch[t];
71 }
72 //Ans += t;
73 return Ans;
74 }
75
76 void prepare(){
77 memset(Max, 0, sizeof( Max ));
78 Pos = 0;//Pos为块状链表的标号
79 list[Pos++].init();
80 insert(root[1], root[0], 0);//插入可持久化trie
81 for (int cur = 0, i = 1; i <= n; cur = list[cur].next){
82 int j, M = 0;//M用来记录块的最大值
83 for (j = 0; j < SIZE && i <= n; i++, j++){
84 list[cur].data[j] = data[i];
85 list[cur].size++;
86 insert(root[i + 1], root[i], data[i]);//插入可持久化trie
87 int M2 = data[i];
88 //M2 = find(root[i + 1], root[cur * SIZE], list[cur].data[j]);
89 //printf("%d\n", M2);
90 //if (M2 == data[i]) M2 = 0;//显然如果是它自己不如不加即直接从开头一直异或到i
91 //Max[cur][cur] = M2;
92 for (int k = Pos - 1; k >= 0; k--){
93 int tmp = find(root[i + 1], root[k * SIZE], data[i]);
94 //if (tmp == data[i]) tmp = 0;
95 if ((M2 ^ data[i]) < (tmp ^ data[i])) M2 = tmp;
96 Max[k][cur] = max(Max[k][cur], M2 ^ data[i]);//顺便利用O(sqrt(n))的时间预处理出Max数组
97 }
98 }
99 //创建新块
100 if (j == SIZE){
101 list[Pos].init();
102 list[cur].next = Pos++;
103 }
104 }
105 //printf("%d\n", root[1]->ch[0]->ch[1]->num);
106 }
107 int query(int l, int r){
108 int x = (l - 1) / SIZE, y = (r - 1) / SIZE;//x代表l和r所代表的块
109 int Ans = 0;
110 if (x == y){
111 for (int i = l; i <= r; i++)
112 Ans = max(Ans, find(root[r + 1], root[l - 1], data[i]) ^ data[i]);
113 return Ans;
114 }else{
115 if (x <= y - 1) Ans = Max[x ][y - 1];
116 //for (int i = r; i >= l; i--) if ((data[i] ^ data[i - 1]) == 32767) printf("fuck");
117 for (int i = l; i <= ((x + 1) * SIZE) && i <= n; i++) Ans = max(Ans, find(root[r + 1], root[l - 1], data[i]) ^ data[i]);
118 for (int i = r; i > y * SIZE; i--) Ans = max(Ans, find(root[r + 1], root[l - 1], data[i]) ^ data[i]);
119 return Ans;
120 //for (int i = l; i <= r; i++)
121 // Ans = max(Ans, find(root[r + 1], root[l - 1], data[i]) ^ data[i]);
122 //return Ans;
123 }
124 }
125 //处理询问
126 void work(){
127 int last_ans = 0;
128 for (int i = 1; i <= m; i++){
129 int x, y, l, r;
130 scanf("%d%d", &l, &r);
131 //l--;
132 //l = min(((ll)((ll)x + (ll)last_ans) % n) + 1 , ((ll)((ll)y + (ll)last_ans) % n)+ 1);
133 //r = max(((ll)((ll)x + (ll)last_ans) % n) + 1 , ((ll)((ll)y + (ll)last_ans) % n)+ 1);
134 last_ans = query(l, r);
135 printf("%d\n", last_ans);
136 }
137 }
138 //单纯的插入一个数
139 void build(Node *&b, int x){
140 Node *u = b;
141 for (int i = 30; i >= 0; i--){
142 int t = (((1 << i) & x) == 0 ? 0 : 1);//表示这一位是否是0
143 if (u->ch[t] == NULL){
144 u->ch[t] = NEW();
145 u->ch[t]->val = t;
146 u->ch[t]->num = 0;//注意,这里仅仅只是建树,所以不能改数字
147 }
148 u = u->ch[t];
149 }
150 return;
151 }
152 void init(){
153 //读入+建初始树
154 scanf("%d%d", &n, &m);
155 for (int i = 0; i < N; i++) root[i] = NULL;
156 root[0] = NEW();
157 data[0] = 0;
158 for (int i = 1; i <= n; i++){
159 scanf("%d", &data[i]);
160 data[i] = data[i] ^ data[i - 1];
161 build(root[0], data[i]);
162 //printf("%d\n", data[i]);
163 }
164 build(root[0], 0);//记得加0
165 //printf("%d", root[0]->val);
166 }
167 void debug(){
168 insert(root[1], root[0], 0);
169 insert(root[2], root[1], 1);
170 insert(root[3], root[2], 6);
171 printf("%d\n", find(root[3], root[1], 6));
172 }
173
174 int main(){
175 #ifdef LOCAL
176 freopen("data.txt", "r", stdin);
177 freopen("out.txt", "w", stdout);
178 #endif
179 init();
180 prepare();
181 work();
182 printf("%d\n", tot);
183 //debug();
184 return 0;
185 }