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;
}

 

posted @ 2020-03-14 19:28  zlc0405  阅读(108)  评论(0编辑  收藏  举报