题面

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

鄙人不才,如果有什么问题请随便提问。