HDU6579 Operation(线性基)
题意:
有两种操作:
- 0 l r 在区间l,r里面选择一些数,使得他们的异或和最大,并输出这个最大值。
- 1 x 将x推进序列,序列长度加1。
题解:
看了网上的线性基才会做,知识盲区...
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int mx = 1e6+5; typedef long long ll; int sum[mx][32]; int pos[mx][32]; int tot; void add(int num) { ++tot; for (int i = 0; i < 32; i++) { sum[tot][i] = sum[tot-1][i]; pos[tot][i] = pos[tot-1][i]; } int now = tot; for (int i = 30; i >= 0; i--) { if (num & (1<<i)) { if (sum[tot][i] == 0) { sum[tot][i] = num; pos[tot][i] = now; break; } if (now > pos[tot][i]) { swap(now, pos[tot][i]); swap(num, sum[tot][i]); } num ^= sum[tot][i]; } } } int query(int l, int r) { int ans = 0; for (int i = 30; i >= 0; i--) { if (sum[r][i] && pos[r][i] >= l) { ans = std::max(ans, ans ^ sum[r][i]); } } return ans; } int main() { int T; scanf("%d", &T); while (T--) { int lastans = 0; tot = 0; int n, m, num; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d", &num); add(num); } while (m--) { int op, l, r; scanf("%d", &op); if (op == 0) { scanf("%d%d", &l, &r); l = (l ^ lastans) % n + 1; r = (r ^ lastans) % n + 1; if (l > r) swap(l, r); lastans = query(l, r); printf("%d\n", lastans); } else { scanf("%d", &r); add(r ^ lastans); n++; } } } return 0; }