(区间线性基) 2017西安区域赛 A XOR

这题做法很早就想到了,就是先对ai^=(~k),消去k的位对查询区间异或和最大值的影响,然后查询区间[l,r]区间异或和最大值ans,答案就是k|ans,但是卡在了区间异或最大值这里,我当时只会线性基on插区间最大值,帅帅在用线段树做,但是re了,

(多说一句,uva真的坑,只要不ce和re全判ac,什么垃圾oj。。)后来我们发现判题全ac就没继续打了

思路:思路就是上面说的,唯一的难点就是区间异或最大值了,详见代码

Consider an array AAA with n elements . Each of its element is A[i]A[i]A[i] (1≤i≤n)(1 \le i \le n)(1≤i≤n) . Then gives two integers QQQ, KKK, and QQQ queries follow . Each query , give you LLL, RRR, you can get ZZZ by the following rules.

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

Please calculate the maximum ZZZ for each query .

Input

Several test cases .

First line an integer TTT (1≤T≤10)(1 \le T \le 10)(1≤T≤10) . Indicates the number of test cases.Then TTT test cases follows . Each test case begins with three integer NNN, QQQ, KKK (1≤N≤10000, 1≤Q≤100000, 0≤K≤100000)(1 \le N \le 10000,\ 1 \le Q \le 100000 , \ 0 \le K \le 100000)(1≤N≤10000, 1≤Q≤100000, 0≤K≤100000) . The next line has NNN integers indicate A[1]A[1]A[1] to A[N]A[N]A[N] (0≤A[i]≤108)(0 \le A[i] \le 10^8)(0≤A[i]≤108). Then QQQ lines , each line two integer LLL, RRR (1≤L≤R≤N)(1 \le L \le R \le N)(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

题目来源

ACM-ICPC 2017 Asia Xi'an

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string>
#include<string.h>
#include<map>
//#define ll long long
#define ll int
#include <iostream>
#include <math.h>
using namespace std;
#define maxn 10000+5
ll d[maxn][35],a[maxn],pos[maxn][35];//线性基数组
void add(int now,ll x)//添加x
{
    for(int i=30;i>=0;i--) d[now][i]=d[now-1][i],pos[now][i]=pos[now-1][i];
    int h=now;
    for(int i=30;i>=0;i--)
    {
        if(x&(1ll<<i))
        {
            if(d[now][i])
            {
                if(pos[now][i]<h)
                {
                    swap(pos[now][i],h);
                    swap(d[now][i],x);
                }
                x^=d[now][i];
            }
            else
            {
                d[now][i]=x;
                pos[now][i]=h;
                break;
            }
        }
    }
}
ll Max(int l,int r)//从数组中去任意个使异或和最大
{
    ll ans=0;
    for(int i=30;i>=0;i--)
    {
        if((pos[r][i]>=l)&&((ans^d[r][i])>ans)) ans^=d[r][i];
    }
    return ans;
}
int main()
{
    /*int n;
    while(scanf("%d",&n)!=EOF)
    {
        memset(d,0,sizeof(d));
        for(int i=1;i<=n;i++)
        {
            ll x;
            cin>>x;
            add(x);
        }
        ll ans=Min();
        cout<<ans<<'\n';
    }*/
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(pos,0,sizeof(pos));
        memset(d,0,sizeof(d));
        int n,q,k;
        scanf("%d %d %d",&n,&q,&k);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            a[i]&=(~k);
        }
        for(int i=1;i<=n;i++)
        {
            add(i,a[i]);
        }
        while(q--)
        {
            int l,r;
            scanf("%d %d",&l,&r);
            int ans=Max(l,r);
            printf("%d\n",k|ans);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_43497140/article/details/106926602