【2017西安邀请赛:A】XOR(线段树+线性基)

前言:虽然已经有很多题解了,但是还是想按自己的理解写一篇。

思路:首先分析题目

   一、区间操作 —— 线段树

   二、异或操作 —— 线性基

   这个两个不难想,关键是下一步的技巧

    “或”运算 就是两个数的二进制中,对应位 只要有1,那么就是该位结果就是 1,所以要想k“或”运算后的结果尽量大,

   就需要异或出的数,各个位上的1尽量多。

   线性基的操作,可以求出区间最大异或和,但是我们需要的结果是  “或”运算。

   所以我们可以将 k 取反,然后把所有数在加入线性基之前,全部 “与”运算一遍,再加入线性基。

   这样,线性基中的每一位,全部都是能使得k变大的数了,因为k的二进制上的每一位 1 的位置,线性基中都是0。

扫描二维码关注公众号,回复: 7733675 查看本文章

   所以,我们只需要求, k 异或 线性基中最大异或和 。

  

//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#pragma GCC optimize(2)
#include <bits/stdc++.h>
#include<unordered_set>

using namespace std;
typedef double dou;
typedef long long ll;
typedef pair<int, int> pii;
typedef map<int, int> mii;

#define pai acos(-1.0)
#define M 10050
#define inf 0x3f3f3f3f
#define mod 1000000007
#define IN inline
#define W(a) while(a)
#define lowbit(a) a&(-a)
#define left k<<1
#define right k<<1|1
#define lson L, mid, left
#define rson mid + 1, R, right
#define ms(a,b) memset(a,b,sizeof(a))
#define Abs(a) (a ^ (a >> 31)) - (a >> 31)
#define random(a,b) (rand()%(b+1-a)+a)
#define false_stdio ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)

int T;
int n, q, k;
int tmp, x, y, z;

struct Data {
    int num[35];
    void insert(int t) {
        for (int i = 31; i >= 0; i--) {
            if (t >> i & 1) {
                if (!num[i]) { num[i] = t; break; }
                t ^= num[i];
            }
        }
    }
}tree[M << 2], ans;

IN void Updata(int L, int R, int k,int pos) {
    tree[k].insert(tmp);
    if (L == R)return;
    int mid = L + R >> 1;
    if (pos <= mid)Updata(lson, pos);
    else Updata(rson, pos);
}

IN void Query(int L, int R, int k) {
    if(x<=L && R<=y){
        for (int i = 31; i >= 0; i--) {
            if (tree[k].num[i])ans.insert(tree[k].num[i]);
        }
        return;
    }
    int mid = L + R >> 1;
    if (x <= mid)Query(lson);
    if (y > mid)Query(rson);
}

IN int read() {//快读
    int v = 0, f = 0; char ch = getchar();
    W(!isdigit(ch)) { f |= ch == '-'; ch = getchar(); }
    W(isdigit(ch)) { v = (v << 3) + (v << 1) + (ch ^ 48); ch = getchar(); }
    return f ? -v : v;
}

int main() {
    T = read();
    W(T--) {
        n = read(), q = read(), k = read();
        for (int i = 1; i <= n; i++) {
            tmp = read();
            tmp &= (~k);//关键的一步
            Updata(1, n, 1, i);
        }
        W(q--) {
            ms(ans.num, 0);
            x = read(), y = read();
            Query(1, n, 1);
            z = k;
            for (int i = 31; i >= 0; i--)z = max(z, z ^ ans.num[i]);
            printf("%d\n", z);
        }
    }
    return 0;
}

   

   

猜你喜欢

转载自www.cnblogs.com/caibingxu/p/11788485.html