隐藏
「bsoj4630」区间异或值 - 线性基 | Bill Yang's Blog

路终会有尽头,但视野总能看到更远的地方。

0%

「bsoj4630」区间异或值 - 线性基

题目大意

    有一个长度为$n$的序列,支持两种操作:
      $0\,x\,y$:把$x$位置上的数换成$y$。
      $1\,x\,y$:在$[x,y]$中,请你任选一些数使他们的异或和最大。


题目分析

不妨用线段树维护线性基,每次单点修改时暴力重构线性基,询问时合并线性基。
因为线性基最多$63$个,因此时间复杂度是$O(n\log n63^2)$。


代码

此题重载运算符略微卡常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<climits>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;

typedef long long LL;

inline const LL Get_Int() {
LL num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}

const int maxn=30005,MAX_BASE=63;

struct Linear_Bases {
LL b[MAX_BASE+5];
Linear_Bases() {
fill(b,b+MAX_BASE+1,0);
}
Linear_Bases operator + (LL num) {
Linear_Bases a=*this;
for(int j=MAX_BASE; j>=0; j--)
if(num>>j&1) {
if(a.b[j]) { //该位存在基
num^=a.b[j];
continue;
}
a.b[j]=num;
for(int k=j-1; k>=0; k--)if(a.b[j]>>k&1)a.b[j]^=a.b[k];
for(int k=j+1; k<=MAX_BASE; k++)if(a.b[k]>>j&1)a.b[k]^=a.b[j];
break;
}
return a;
}
void operator += (const LL num) {
*this=*this+num;
}
Linear_Bases operator + (const Linear_Bases& b) {
Linear_Bases a=*this;
for(int i=0; i<=MAX_BASE; i++)
if(b.b[i])a+=b.b[i];
return a;
}
void operator += (const Linear_Bases b) {
*this=*this+b;
}
LL cal() { //最大异或和
LL ans=0;
for(int i=0; i<=MAX_BASE; i++)ans^=b[i];
return ans;
}
};

struct Segment_Tree {
struct Tree {
int left,right;
Linear_Bases lb;
Tree(int l=0,int r=0):left(l),right(r),lb(Linear_Bases()) {}
} tree[maxn<<2];
#define ls index<<1
#define rs index<<1|1
void build(int index,int Left,int Right,LL* a) {
tree[index]=Tree(Left,Right);
if(Left==Right) {
tree[index].lb+=a[Left];
return;
}
int mid=(Left+Right)>>1;
build(ls,Left,mid,a);
build(rs,mid+1,Right,a);
push_up(index);
}
void push_up(int index) {
tree[index].lb=tree[ls].lb+tree[rs].lb;
}
void modify(int index,int target,LL v) {
if(tree[index].left>target||tree[index].right<target)return;
if(tree[index].left==tree[index].right) {
tree[index].lb=Linear_Bases()+v;
return;
}
modify(ls,target,v);
modify(rs,target,v);
push_up(index);
}
Linear_Bases query(int index,int Left,int Right) {
if(tree[index].left>Right||tree[index].right<Left)return Linear_Bases();
if(Left<=tree[index].left&&Right>=tree[index].right)return tree[index].lb;
return query(ls,Left,Right)+query(rs,Left,Right);
}
} st;

int n,q;
LL a[maxn];

int main() {
n=Get_Int();
q=Get_Int();
for(int i=1; i<=n; i++)a[i]=Get_Int();
st.build(1,1,n,a);
while(q--) {
int opt=Get_Int(),x=Get_Int();
LL y=Get_Int();
if(opt==0)st.modify(1,x,y);
else {
Linear_Bases lb=st.query(1,x,y);
printf("%lld\n",lb.cal());
}
}
return 0;
}

姥爷们赏瓶冰阔落吧~