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]中呢?
  • 這時候我們就需要另外一個數組pos[r][i]pos[r][i]表示[1,r][1, r]區間滿足上述“從右往左插入向量”條件的線性基向量的位置。
  • 這個數組在我們構建前綴線性基時也有重要作用!!!首先我們無論是p[r]p[r]還是pos[r]pos[r]在開始的時候都需要繼承p[r1]p[r-1]pos[r1]pos[r-1]. 這裏數組pos[ ][ ]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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章