CodeForces - 1100F - Ivan and Burgers【前缀_线性基】

CodeForces - 1100F - Ivan and Burgers

题意

  • 给定一个长度为n的数列. 然后有q次查询,查询[L, R]区间中的某个子集异或和最大。

思路

  • 我们定义 p [ r ] [ i ] p[r][i] [ 1 , r ] [1, r] 的线性基,并且这个线性基区别于平常从左往右插入,这个是从右往左插。
  • 于是我们查询 [ L , R ] [L, R] 某些向量异或和最大时,就可以完美避开前 [ 1 , L ) [1, L) 向量的影响。直接遍历线性基 p [ r ] p[r] ,如果插入向量的位置在 [ L , R ] [L, R] 范围内,那么就取异或最大咯~,否则直接舍掉
如何保证我们所取的向量在 [ L , R ] [L, R] 中呢?
  • 这时候我们就需要另外一个数组 p o s [ r ] [ i ] pos[r][i] 表示 [ 1 , r ] [1, r] 区间满足上述“从右往左插入向量”条件的线性基向量的位置。
  • 这个数组在我们构建前缀线性基时也有重要作用!!!首先我们无论是 p [ r ] p[r] 还是 p o s [ r ] pos[r] 在开始的时候都需要继承 p [ r 1 ] p[r-1] p o s [ r 1 ] pos[r-1] . 这里数组 p o s [   ] [   ] pos[ \ ][ \ ] 的作用就是更新当前线性基的 p [ r ] [ i ] p[r][i] 为最靠右的向量。

插入向量的代码

void add(int x, int R)
{
    int id = R;
    for(int i = maxBit - 1; i >= 0; -- i ) p[R][i] = p[R - 1][i], pos[R][i] = pos[R - 1][i];
    for(int i = maxBit - 1; i >= 0; -- i )
    {
        if(x >> i & 1)
        {
            if(!p[R][i]) { p[R][i] = x; pos[R][i] = id; break; }
            if(pos[R][i] < id) { swap(p[R][i], x); swap(pos[R][i], id); }
            x ^= p[R][i];
        }
    }
}

完整代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read()
{
    int x = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -f; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    return x * f;
}

const int maxN = 500005;
const int maxBit = 21;

int n, c[maxN];
int p[maxN][maxBit];
int pos[maxN][maxBit];

void add(int x, int R)
{
    int id = R;
    for(int i = maxBit - 1; i >= 0; -- i ) p[R][i] = p[R - 1][i], pos[R][i] = pos[R - 1][i];
    for(int i = maxBit - 1; i >= 0; -- i )
    {
        if(x >> i & 1)
        {
            if(!p[R][i]) { p[R][i] = x; pos[R][i] = id; break; }
            if(pos[R][i] < id) { swap(p[R][i], x); swap(pos[R][i], id); }
            x ^= p[R][i];
        }
    }
}

int main()
{
    n = read();
    for(int i = 1; i <= n; ++ i )
    {
        c[i] = read();
        add(c[i], i);
    }
    int QAQ; QAQ = read();
    while(QAQ -- )
    {
        int l, r; l = read(); r = read();
        int ans = 0;
        for(int i = maxBit - 1; i >= 0; -- i )
            if(pos[r][i] >= l)
                ans = max(ans, ans ^ p[r][i]);
        cout << ans << endl;
    }
    return 0;
}
发布了273 篇原创文章 · 获赞 76 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_44049850/article/details/104734075