2017 ACM-ICPC Asia Xi'an Problem A XOR(異或線性基 )
阿新 • • 發佈:2018-02-16
problem 線段樹 all gpo efi printf 異或 bre %d
題目鏈接 2017西安賽區 Problem A
題意 給定一個數列,和$q$個詢問,每個詢問中我們可以在區間$[L, R]$中選出一些數。
假設我們選出來的這個數列為$A[i_{1}]$, $A[i_{2}]$, ..., $A[i_{t}]$
求$K$ $or$ $($$A[i_{1}]$ $xor$ $A[i_{2}]$ ... $xor$ $A[i_{t}]$$)$的最大值
首先常規操作,每次在線段樹上求出區間$[L, R]$代表的線性基。
然後把這個線性基中所有$K$的二進制表示為$1$的位全部削成$0$。
這樣得到了新的不超過$30$個數,把新的這些數單獨用一個線性基表示。
最後答案就是新的這個線性基中選出某些數能異或出來的最大值或上$K$的結果。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) #define ls i << 1 #define rs i << 1 | 1 #define lson i << 1, L, mid #define rson i << 1 | 1, mid + 1, R const int N = 1e4 + 10; const int all = (1 << 27) - 1; int n, q, k; int T; int a[N], cnt; struct lb{ int d[30]; void clear(){ memset(d, 0, sizeof d); cnt = 0; } bool ins(int val){ dec(i, 28, 0) if (val & (1 << i)){ if (!d[i]){ d[i] = val; break; } val ^= d[i]; } return val > 0; } int qmax(){ int ret = 0; dec(i, 28, 0) if ((k | (ret ^ d[i])) > (k | ret)) ret ^= d[i]; return k | ret; } }; lb t[N << 3], c; lb merge(const lb &n1, const lb &n2){ lb ret = n1; dec(i, 28, 0) if (n2.d[i]) ret.ins(n2.d[i]); return ret; } void build(int i, int L, int R){ if (L == R){ t[i].ins(a[L]); return; } int mid = (L + R) >> 1; build(lson); build(rson); t[i] = merge(t[ls], t[rs]); } lb query(int i, int L, int R, int l, int r){ if (L == l && R == r) return t[i]; int mid = (L + R) >> 1; if (r <= mid) return query(lson, l, r); else if (l > mid) return query(rson, l, r); else return merge(query(lson, l, mid), query(rson, mid + 1, r)); } int main(){ scanf("%d", &T); while (T--){ scanf("%d%d%d", &n, &q, &k); rep(i, 0, 4e4) t[i].clear(); rep(i, 1, n) scanf("%d", a + i); build(1, 1, n); while (q--){ int x, y; scanf("%d%d", &x, &y); lb now = query(1, 1, n, x, y); cnt = all ^ k; dec(i, 28, 0) now.d[i] &= cnt; c.clear(); dec(i, 28, 0) if (now.d[i]) c.ins(now.d[i]); printf("%d\n", c.qmax() | k); } } return 0; }
2017 ACM-ICPC Asia Xi'an Problem A XOR(異或線性基 )