cf1100 F. Ivan and Burgers

传送门
给出(m)个查询,查询([l,r])的最大异或和

可删除线性基
每次插入值的时候就进行线性基更新,同时维护下当前二进制第i位的最后更新点
然后把查询离线,按照右区间排序
查询时,看线性基最后更新时间是否在当前的区间。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int MaxBasis = 20;///二进制位数
struct Linear_Basis {
    ll base[MaxBasis + 10]; bool rel; int sz;
    int tim[MaxBasis];
    vector<ll> Basis;/// 线性基(向量)
    Linear_Basis() { memset(base, 0, sizeof(base)); rel = false; sz = 0; Basis.clear();}
    void init() {
        memset(base, 0, sizeof(base)); rel = false; sz = 0; Basis.clear();
        memset(tim, 0, sizeof(tim));
    }
    bool add(ll x, int t) { //加入线性基中
        for (int i = MaxBasis; i >= 0; --i) {
            if (!(x >> i & 1)) continue;
            if (base[i]) {if(t > tim[i]) swap(t, tim[i]), swap(x, base[i]); x ^= base[i];}
            else {
                base[i] = x, ++sz; tim[i] = t;
                return 1;
            }
        }
        rel = true;
        return 0;
    }
    ll Max(int t) { //取最大
        ll ans = 0;
        for(int i = MaxBasis; i >= 0; i--) 
            if(t <= tim[i] && !(ans >> i & 1)) ans ^= base[i];
        return ans;
    }
} lb;
const int N = 5e5 + 5;
ll a[N], Ans[N];
struct Query{
    int l, r, id;
} q[N];
int main(){
    int n; scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
    int m; scanf("%d", &m);
    for(int i = 1; i <= m; i++) {
        scanf("%d%d", &q[i].l, &q[i].r); q[i].id = i;
    }
    sort(q + 1, q + m + 1, [](Query &a, Query &b){ // 右区间排序
        return a.r < b.r;
    });
    for(int i = 1, j = 1; i <= n; i++) {
        lb.add(a[i], i);
        for(; j <= m && q[j].r <= i; j++) Ans[q[j].id] = lb.Max(q[j].l);
    }
    for(int i = 1; i <= m; i++)
        printf("%lld
", Ans[i]);
    return 0;
}
I‘m Stein, welcome to my blog
原文地址:https://www.cnblogs.com/Emcikem/p/14289882.html