1. 程式人生 > 實用技巧 >HDU 6845(杭電多校7-B)(線性基)

HDU 6845(杭電多校7-B)(線性基)

這不是一篇題解, 如果您來看這題怎麼做可以關了


起因是不知道題解裡那句 "對於 \(n\) 個人的每個字首,求出從後往前插入的線性基,並記錄每個基是哪個人提供的,這是一個經典演算法" 所指的經典演算法是啥, 讀了程式碼之後知道, 原來演算法流程是這樣的: 從前往後掃, 當前是第 \(i\) 個向量 \(x\) 時, 按正常插入線性基從高位往低位掃 x, 第 \(j\) 位遇到 \(1\) 時檢查 \(bas[j][0]\) 是否為 \(0\), 不為 \(0\) 時, \(bas[j][0] = x\), \(bas[j][1]=i\); 否則, 執行 \(if(ti>bas[j][1]) swap(bas[j][0],x),swap(bas[j][1],ti)\)

, \(ti\) 初值為 \(i\), 後面正常 \(x^=bas[j][0]\), 繼續掃.

#include <bits/stdc++.h>
using namespace std;
#define ll long long

const int maxn = 1e5 + 5;

int bas[maxn][30][2], p[maxn], n, m, x, y, q, opt, b[maxn], w, ti, T;

int main() {
    scanf("%d", &T);
    while (T--) {
        scanf("%d%d", &n, &q);
        for (int i = 1; i <= n; i++) {
            scanf("%d%d", &m, &p[i]);
            b[i] = b[i - 1];
            for (int k = 0; k < 30; k++)
                bas[i][k][0] = bas[i - 1][k][0],
                bas[i][k][1] = bas[i - 1][k][1];
            for (int j = 1; j <= m; j++) {
                scanf("%d%d", &x, &y);
                b[i] ^= x;
                y ^= x;
                ti = i;
                for (int k = 29; k >= 0; k--) {
                    if (!(y >> k & 1)) continue;
                    if (!bas[i][k][0]) {
                        bas[i][k][0] = y;   //該位置的向量是什麼
                        bas[i][k][1] = ti;  //歸哪個向量管
                        break;
                    } else {
                        if (bas[i][k][1] < ti)
                            swap(y, bas[i][k][0]), swap(ti, bas[i][k][1]);
                        y ^= bas[i][k][0];
                    }
                }
            }
        }
        for (int i = 1; i <= q; i++) {
            scanf("%d%d%d", &opt, &x, &y);
            if (opt == 1)
                p[x] = y;
            else {
                scanf("%d", &w);
                w ^= b[y] ^ b[x - 1];
                for (int j = 29; j >= 0; j--) {
                    if (!bas[y][j][0] || bas[y][j][1] <= x - 1) continue;
                    if ((w ^ p[bas[y][j][1]]) >> j & 1) w ^= bas[y][j][0];
                }
                printf("%d\n", w);
            }
        }
    }
}