题面
Solution
发现题目要求三个数据,,
,
要求
满足在区间
都有
,那么不就是让
最大吗?发现整个区间不需要修改,用线段树维护一下最大值和对应的编号即可
接下来让我们求
, 一段区间的
,emmm,想必大家都知道,一个数异或他自己等于
,那么我们可以开个
数组用前缀和预处理一下,那么区间
的异或和就是
,在把前面找到的
异或掉, 多异或一个
即可
最后看一下
怎么求,暴力找太容易T掉了,让我们想一想怎么优化它。我们知道
的运算法则是相异为一相同为零,那么是不是说,相异的越多,答案也就越优?是的!
现在是怎么求相异最多的
的问题,数据范围只有
,那么
的二进制长最多也只有
位,让我们从高位向低位枚举,看看能不能添加上那个相异的数即可
为什么是从高往低呢?因为高位上的数对答案贡献更大,且低位的数更加灵活,如果先确定低位,可能一些更优的高位就找不到了。
Code
/*
Work by: Suzt_ilymics
Knowledge: ??
Time: O(??)
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define int long long
#define orz cout<<"lkp AK IOI!"<<endl
#define lson i << 1
#define rson i << 1 | 1
using namespace std;
const int MAXN = 1e6+6;
const int INF = 1;
const int mod = 1;
int n, q, s, w;
int a[MAXN], sum[MAXN];
int read(){
int s = 0, f = 0;
char ch = getchar();
while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while(isdigit(ch)) s = (s << 1) + (s << 3) + ch - '0' , ch = getchar();
return f ? -s : s;
}
namespace getK{//建立一棵线段树,维护区间最大值及其编号
struct Tree{
int len, max, bh;
}tree[MAXN << 2];
void push_up(int i){//上传
tree[lson].max >= tree[rson].max ? (tree[i].max = tree[lson].max, tree[i].bh = tree[lson].bh) : (tree[i].max = tree[rson].max, tree[i].bh = tree[rson].bh);
}
void build(int i, int l, int r){
tree[i].len = r - l + 1;
if(l == r){
tree[i].max = a[l], tree[i].bh = l;//建树
return ;
}
int mid = (l + r) >> 1;
build(lson, l, mid), build(rson, mid + 1, r);
push_up(i);
}
Tree get_max(int i, int l, int r, int L, int R){//取最大值
if(L <= l && r <= R){
return tree[i];
}
int mid = (l + r) >> 1;
Tree ans;
if(mid < L) return get_max(rson, mid + 1, r, L, R);//如果全在右边,就搜索右边的
else if(mid >= R) return get_max(lson, l, mid, L, R);//如果全在左边,就搜索左边的
else {//否则,两段都选,并且将这两段合并
Tree ansl = get_max(lson, l, mid, L, mid), ansr = get_max(rson, mid + 1, r, mid + 1, R);
ansl.max >= ansr.max ? (ans.max = ansl.max, ans.bh = ansl.bh) : (ans.max = ansr.max, ans.bh = ansr.bh);
return ans;
}
}
}
int getW(int S){//找到最大的W,根据xor的规则,与S同位相异的数越多越好,越大越好
S ^= ((1 << 30) - 1);
// cout<<"S:"<<(((S >> 2) % 2) << 2)<<endl;
int res = 0;
for(int i = 31; i >= 0; --i){//从大到小查找
if((res ^ (((S >> i) % 2)) << i) <= w) res ^= (((S >> i) % 2) << i);
}
return res;
}
int b[MAXN];
#undef int
int main()
{
#define int long long
n = read(), q = read(), s = read(), w = read();
for(int i = 1; i <= n; ++i){
a[i] = read(); //读入
b[i] = a[i];//存到b数组里
sum[i] = sum[i - 1] ^ a[i];//做一个前缀和 ,方便求S
a[i] = a[i] ^ s;// 提前异或好
}
// cout<<cnt<<endl;
// cout<<(sum[5] ^ sum[0] ^ b[4])<<" "<<(6 ^ 1)<<endl;;
// for(int i = 1; i <= n; ++i) cout<<a[i]<<" ";
// cout<<endl;
// for(int i = 1; i <= n; ++i) cout<<sum[i]<<" ";
// cout<<endl;
getK::build(1, 1, n);//建树
for(int i = 1, l, r; i <= q; ++i){
l = read(), r = read();
int k = getK::get_max(1, 1, n, l, r).bh;
int S = sum[r] ^ sum[l - 1] ^ b[k];
int W = getW(S);
// cout<<"k:"<<k<<" S:"<<S<<" W:"<<W<<endl<<"ans:";
printf("%lld\n", (S ^ W));
}
return 0;
} 鄙人不才,如果有什么问题请随便提问。

京公网安备 11010502036488号