前缀线性基是建立在线性基得基础上的,还不会线性基请看:线性基浅谈
线性基用来处理整个区间异或的最大值、最小值等等
前缀线性基用来维护整个区间中的一段区间的最大值、最小值等等
前缀线性基的构造思路:是对于i都建立一个1~i的数组成的线性基。
比如4个数,就建1 1、2 1、2、3 1、2、3、4 这里的1 2 3 4表示第1个数,第2个数...,不是真实的值
我们把 1 叫第一个基 1、2叫第二个基 1、2、3 叫第三个基 1、2、3、4 叫第四个基
构造第i个基的时候,线从i-1个基复制过来,然后加上第i个数,如果对于基种某个位置上的数有比他更新的数就替换了(这样保证了对于某个右端点R能尽可能的用靠近R的数作为基,也就保证了所有[L,R]中的数都尽可能的参与构造这个数,比所说对于第五个基的第3个位置,如果第四个数和第二个数都能放在这个位置,就放第四个数,因为查询区间[3,5]能用3,4,5的数构造这个数,包含了4,查询区间[2,5]能用2,3,4,5的数构造这个数,也就是说对于[2,5]他无所谓用第四个数还是第二个数因为他都能用,但是[3,5]区间只能用4,所以当第四个数和第二个数都能放在第3个位置优先用第四个数)
查询的时候:如果要查询[L,R],就找到第R个基,然后记录pos[i],表示第i个位置是那个数,如果pos<l就不算是[L,R]的基
具体看代码:
Operation
OperationTime Limit: 8000/4000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 2840 Accepted Submission(s): 867 Problem Description There is an integer sequence a of length n and there are two kinds of operations:
Input There are multiple test cases. The first line of input contains an integer T(T≤10), indicating the number of test cases.
Output For each type 0 operation, please output the maximum xor sum in a single line.
Sample Input 1 3 3 0 1 2 0 1 1 1 3 0 3 4
Sample Output 1 3
Source 2019 Multi-University Training Contest 1
Recommend |
#include <bits/stdc++.h>
#define FOR(I,S,T) for(int I=(S);I<=(T);I++)
using namespace std;
const int maxn = 5e5 + 5;
int n, N;
struct Guass{
int x[32], pos[32];//最后一个修改i这个位置得数
}a[maxn];
void Insert(int v){
N++;
a[N] = a[N- 1];
int P = N;
for (int i = 31; i >= 0; i--){
if((v >> i) & 1){
if (!a[N].x[i]){
a[N].x[i] = v;
a[N].pos[i] = P;
break;
}else {
if (a[N].pos[i] < P) swap(a[N].pos[i], P), swap(a[N].x[i], v);
v ^= a[N].x[i];
}
}
}
}
int Query(int l, int r){
int res = 0;
for (int i = 31; i >= 0; i--){
if (a[r].pos[i] < l) continue;
if ((res ^ a[r].x[i]) > res) res ^= a[r].x[i];
}
return res;
}
int main(){
int T;
cin >> T;
while (T--){
memset(a[0].x, 0, sizeof(a[0].x));
memset(a[0].pos, 0, sizeof(a[0].pos));
int q;
N = 0;
int ans = 0;
scanf("%d%d", &n, &q);
for (int i = 1; i <= n; i++){
int x;
scanf("%d", &x);
Insert(x);
}
for (int i = 1; i <= q; i++){
int ope = 0;
scanf("%d", &ope);
if (ope == 0){
int x = 0, y = 0;
scanf("%d%d", &x, &y);
x = (x ^ ans) % N + 1;
y = (y ^ ans) % N + 1;
if (x > y) swap(x, y);
ans = Query(x, y);
// cout << x << " " << y << endl;
printf("%d\n", ans);
}else{
int x;
scanf("%d", &x);
x ^= ans;
Insert(x);
}
}
}
return 0;
}