HDU 6845(杭電多校7-B)(線性基)
阿新 • • 發佈:2020-09-09
這不是一篇題解, 如果您來看這題怎麼做可以關了
起因是不知道題解裡那句 "對於 \(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)\)
#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); } } } }