线性基
struct Base{
ll dr[65], tmp[65];
int cnt, flag;
void init() {
flag = 0;
memset(dr, 0, sizeof(dr));
memset(tmp, 0, sizeof(tmp));
}
//插入
void insert(ll c) {
for (int i = 60; i >= 0; i--) {
if (c &(1ll<<i)) {
if (!dr[i]) {dr[i]=c;return;}
c = c^dr[i];
}
}
flag = 1;
}
//查询最大值
ll query_max(ll res = 0) {
for (int i = 60; i >= 0; i--) {
if ((dr[i]^res) > res) res = res^dr[i];
}
return res;
}
//查询最小值
ll query_min(ll res = 0) {
for (int i = 0; i <= 60; i++) {
if (dr[i]) return dr[i];
}
return -1;
}
//第k小
void rebuild() {
cnt = 0;
for(int i = 60; i >= 0; i--)
for(int j = i-1; j >= 0; j--)
if(dr[i]&(1ll<<j))
dr[i] ^= dr[j];
for (int i = 0; i <= 60; i++)
if(dr[i])
tmp[cnt++] = dr[i];
}
ll kthquery(ll k) {
ll res = 0;
if(flag) k--;
if (k >= (1LL<<cnt)) return -1;
for (int i = 60; i >= 0; i--)
if (k&(1ll<<i)) res ^= tmp[i];
return res;
}
};
//合并两个线性基
Base merge(Base a, Base b) {
Base res = a;
for(int i = 60; i >= 0; i--) {
if(b.dr[i]) res.insert(b.dr[i]);
}
return res;
}
前缀线性基
struct pre_base{
struct Base{
pair<ll, int> dr[66];
int cnt;
void clear() {
memset(dr, 0, sizeof(dr));
cnt = 0;
}
void operator=(const Base s) {
for(int i = 0; i <= 60; i++) dr[i] = s.dr[i];
cnt = s.cnt;
}
void insert(pair<ll, int> s) {
for(int i = 60; i >= 0; i--) {
if(s.first&(1ll<<i)) {
if(!dr[i].first) {dr[i] = s;cnt++;return;}
else {
if(s.second > dr[i].second) swap(s, dr[i]);
s.first ^= dr[i].first;
}
}
}
}
};
Base root[maxn];int pos;
Base tmp;int cnt, flag;
void init() {
pos = 0;flag = 0;
}
void insert(ll x) {
pos++;
root[pos] = root[pos-1];
root[pos].insert(make_pair(x, pos));
}
ll query_max(int l, int r) {
ll res = 0;
for(int i = 60; i >= 0; i--) {
if(root[r].dr[i].second >= l && (res ^ root[r].dr[i].first) > res) {
res = res ^ root[r].dr[i].first;
}
}
return res;
}
//query_kth前要rebuild
void rebuild(int l, int r) {
Base ts;ts.clear();
flag = 0;
for(int i = 60; i >= 0; i--) {
if(root[r].dr[i].second >= l)
ts.insert(root[r].dr[i]);
}
if(ts.cnt != (r-l+1)) flag = 1;
for(int i = 60; i >= 0; i--) {
for(int j = i-1; j >= 0; j--) {
if(ts.dr[i].first&(1ll<<j)) {
ts.dr[i].first ^= ts.dr[j].first;
}
}
}
cnt = 0;tmp.clear();
for(int i = 0; i <= 60; i++) {
if(ts.dr[i].first) {
tmp.dr[cnt++] = ts.dr[i];
}
}
}
ll querykth(ll k) {
if(flag && !(--k)) return 0;
if(k >= (1ll<<cnt)) return -1;
ll res = 0;
for(int i = 0; i < cnt; i++) {
if(k&(1ll<<i)) res ^= tmp.dr[i].first;
}
return res;
}
}base;