题目需要用到线性基,之前写过线性基的原理和模版,想看的同学点右边 -> 走你
题意:
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 .
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) .
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');
}
}
}
转载请注明出处!!!
如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢