Operation

 Operation

时间限制: 5 Sec  内存限制: 256 MB

题目描述

There is an integer sequence a of length n and there are two kinds of operations:
0 l r: select some numbers from al...ar so that their xor sum is maximum, and print the maximum value.
1 x: append x to the end of the sequence and let n=n+1.

输入

There are multiple test cases. The first line of input contains an integer T(T≤10), indicating the number of test cases.
For each test case: 
The first line contains two integers n,m(1≤n≤5×105,1≤m≤5×105), the number of integers initially in the sequence and the number of operations.
The second line contains n integers a1,a2,...,an(0≤ai<230), denoting the initial sequence.
Each of the next m lines contains one of the operations given above.
It's guaranteed that ∑n≤106,∑m≤106,0≤x<230.
And operations will be encrypted. You need to decode the operations as follows, where lastans denotes the answer to the last type 0 operation and is initially zero: 
For every type 0 operation, let l=(l xor lastans)mod n + 1, r=(r xor lastans)mod n + 1, and then swap(l, r) if l>r.
For every type 1 operation, let x=x xor lastans.

输出

For each type 0 operation, please output the maximum xor sum in a single line.

样例输入

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

样例输出

1
3

题意:一个序列,两种操作:询问区间异或最大值(可选择区间内任意数异或),在区间末尾加一个数。
思路:首先大思路是用线性基求区间异或最大值,然后考虑怎么求任一区间的异或最大值。考虑贪心,先构造出一个前缀线性基(即第i个线性基代表1-i这些数的基底),然后每次将数加进线性基的时候,贪心的保留位置靠后的数,这样保证每个数只会和比自己位置大的数异或。然后查询区间[L,R]的时候,在第R个线性基里面查询位置大于等于L的基底,并统计答案。
线性基参考博客https://blog.csdn.net/qaq__qaq/article/details/53812883
区间最大异或和参考博客https://www.cnblogs.com/hua-dong/p/10266216.html
#include<bits/stdc++.h>
using namespace std;


struct L_B
{
    int d[30+1],p[30+1];
    L_B()
    {
        memset(d,0,sizeof(d));
        memset(p,0,sizeof(p));
    }

    void operator = (const L_B & s)
    {
        for(int i=0;i<31;i++)d[i]=s.d[i],p[i]=s.p[i];
    }

    bool insert(int val,int pos)
    {
        for (int i=30;i>=0;i--)
            if (val&(1LL<<i))
            {
                if (!d[i])
                {
                    d[i]=val;
                    p[i]=pos;
                    break;
                }

                if(p[i]<pos)
                {
                    int now;

                    now=p[i];
                    p[i]=pos;
                    pos=now;

                    now=d[i];
                    d[i]=val;
                    val=now;
                   // swap((long long)pos,p[i]);
                    //swap((long long)val,d[i]);
                }

                val^=d[i];
            }
        return val>0;
    }
    int query_max(int l)
    {
        int ret=0;
        for (int i=30;i>=0;i--)
            if (p[i]>=l&&(ret^d[i])>ret)
                ret^=d[i];
        return ret;
    }
};


L_B pre[1000050];

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        int ans=0;
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            int a;
            scanf("%d",&a);
            pre[i]=pre[i-1];
            pre[i].insert(a,i);
        }

        while(m--)
        {
            int op;
            scanf("%d",&op);

            if(op==1)
            {
                int x;
                scanf("%d",&x);
                x=x^ans;
                n++;
                pre[n]=pre[n-1];
                pre[n].insert(x,n);
            }
            else
            {
                int l,r;
                scanf("%d %d",&l,&r);

                l=(l^ans)%n+1;
                r=(r^ans)%n+1;
                if(l>r)swap(l,r);
                ans=pre[r].query_max(l);
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}
View Code
 

猜你喜欢

转载自www.cnblogs.com/tian-luo/p/11236545.html