UVA8512线段树维护线性基

​ 题目需要用到线性基,之前写过线性基的原理和模版,想看的同学点右边 -> 走你

题意:

Consider an array A with n elements . Each of its element is A[i] (1≤i≤n) . Then gives two integers Q, K, and Q queries follow . Each query , give you L, R, you can get Z by the following rules.

To get ZZ , at first you need to choose some elements from A[L] to A[R] ,we call them A[i1],A[i2]…A[it] , Then you can get number Z=K or (A[i1] xor A[i2] … xor A[it]) .

Please calculate the maximum Z for each query .

Input

Several test cases .

First line an integer T (1≤T≤10). Indicates the number of test cases.Then TT test cases follows . Each test case begins with three integer N, Q, K (1≤N≤10000, 1≤Q≤100000, 0≤K≤100000). The next line has N integers indicate A[1] to A[N] (0≤A[i]≤108). Then Q lines , each line two integer L, R (1≤L≤R≤N) .

Output

For each query , print the answer in a single line.

样例输入

1
5 3 0
1 2 3 4 5
1 3
2 4
3 5

样例输出

3
7
7

​ 翻译成汉语就是,给你一个T代表T组样例,每组样例有n, q, k,表示一个数组有n个数,有q次询问。下一行给出n个数分别是数组中每个数的值。接下来q行每行两个数l,r,问数组a[l] ~a[r]中选几个数的异或和|k的值最大

问最大值是多少?

思路:

​ 由于异或和|k值最大,这里有个小技巧。就是对数组中的每个数进行a[i] = a[i] & (~k),这样新的数组中最大的异或和|k就是最大值,因此我们只需要求新数组l~r的最大异或和

​ 由于n的数据范围是1e4,q的数据范围是1e5,如果每查询一次重新求一次线性基数组,肯定会超时。因此我们可以利用线段树来维护l~r之间的线性基数组。

​ 再加上各种剪枝,快速读写。用了不到600msA掉

代码:

#include 
#include 
#include 
#include 
#define d int32_t
#define N 10005
#define lson rt<<1
#define rson rt<<1|1
#define mem(a) memset(a, 0, sizeof(a))
#define For(i, star, endd) for(d i = star; i <= endd; i++)
#define Forr(i, endd, star) for (d i = endd; i >= star; i--)
using namespace std;

//快速读
namespace IO {
    const d MX = 1e7;         //1e7 占用内存 11000kb
    char buf[MX];
    d c, sz;
    
    void begin() {            //该方法用于main方法开头位置,可一次性读完全部输入
        c = 0;
        sz = fread(buf, 1, MX, stdin);  //一次性全部读入
    }
    
    inline bool read(int &t) {        //用于从buf中读入每个数
        while (c < sz && buf[c] != '-' && (buf[c] < '0' || buf[c] > '9'))
            c++;
        if (c >= sz) return false;            //若读完整个缓冲块则退出
        bool flag = 0; if(buf[c] == '-') {
            flag = 1;
            c++;
        }
        for(t = 0; c < sz && '0' <= buf[c] && buf[c] <= '9'; c++)
            t = t * 10 + buf[c] - '0';
        if(flag) t = -t;
        return true;
    }
    
    inline void write(int t) {
        if (t > 9) write(t / 10);
        putchar(t % 10 + '0');
    }
}

//全局变量
d k;

//树节点(可存储范围内值的最高位maxn和线性基数组c)
struct node {
    d maxn;
    d c[35];
    void init() {
        mem(c);
    }
    
    void addx(d x) {
        Forr(i, 30, 0) {
            if(x >> i & 1) {
                maxn = i;
                c[i] = x;
                break;
            }
        }
    }
    
    d ansmax() {
        d t = 0;
        Forr(i, maxn, 0) {
            if ((t ^ c[i]) > t) {
                t ^= c[i];
            }
        }
        return t;
    }
    
    node merge(node A) {
        node t;
        t.init();
        Forr(i, maxn, 0) {
            t.c[i] = c[i];
        }
        Forr(i, A.maxn, 0) {
            if (A.c[i]) {
                d x = A.c[i];
                Forr(j, i, 0) {
                    if (x >> j & 1) {
                        if (!t.c[j]) {
                            t.c[j] = x;
                            break;
                        }
                        x ^= t.c[j];
                    }
                    if (x == 0) break;
                }
            }
        }
        t.maxn = max(maxn, A.maxn);
        return t;
    }
}shu[N << 2];

//建树
void Build (d rt, d l, d r) {
    if (l == r) {
        d t;
        IO::read(t);
        t = t & (~k);
        shu[rt].init();
        shu[rt].addx(t);
        return;
    }
    d mid = (l + r) >> 1;
    if (l <= mid) Build(lson, l, mid);
    if (mid < r) Build(rson, mid + 1, r);
    shu[rt] = shu[lson].merge(shu[rson]);
}

//查询
node request (d rt, d l, d r, d L, d R) {
    node t;
    t.init();
    if (l <= L && r >= R) {
        return shu[rt];
    }
    d mid = (L + R) >> 1;
    if (l <= mid && r > mid) return request(lson, l, r, L, mid).merge(request(rson, l, r, mid + 1, R));
    else if(l <= mid) return request(lson, l, r, L, mid);
    else if(r >= mid) return request(rson, l, r, mid + 1, R);
    else return t;
}

d main() {
    IO::begin();
    d T, n, q, l, r;
    IO::read(T);
    while (T--) {
        IO::read(n);
        IO::read(q);
        IO::read(k);
        Build(1, 1, n);
        For(i, 1, q) {
            IO::read(l);
            IO::read(r);
            node t = request(1, l, r, 1, n);
            d ans = (t.ansmax() | k);
            IO::write(ans);
            putchar('\n');
        }
    }
}

转载请注明出处!!!

如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢

你可能感兴趣的:(数论,ACM,线段树)