【2019杭电多校第一场1002 = HDU6579】Operation(在线线性基区间最大异或值查询)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6579

题目:


Operation

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)

Problem Description

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.

Input

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<2^30), 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.

Output

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

Sample Input

1

3 3

0 1 2

0 1 1

1 3

0 3 4

 Sample Output

1

3

 

解题思路:


巨巨们说是CF1100F的原题 ,一样的思路,但是不能离线做,因为l,r的值和之前0操作查询出来的last有关,可以用一个二维数组标记右边界为i时对应的线性基,求区间最大异或值的时候直接调用decode后的r对应的线性基求答案即可,对于1操作,新增一个线性基。

 

ac代码:


#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
const int max_base = 30;
int n, q, l, r, t, op, x, p;
int a[maxn], val[maxn][max_base+3], pos[maxn][max_base+3];
int main()
{
    //freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    cin >> t;
    while(t--)
    {
        int last = 0;

        memset(val,0,sizeof(val));
        memset(pos,0,sizeof(pos));

        cin >> n >> q;
        for(int i = 1; i <= n; i++)
            cin >> a[i];
        //先根据a[]预处理出前n种状态下的线性基,右边界为i
        for(int i = 1; i <= n; i++)
        {
            x = a[i], p = i;
            //在右边界为i-1的基础上更新
            for(int j = max_base; j >= 0; j--)
            {
                val[i][j] = val[i-1][j];
                pos[i][j] = pos[i-1][j];
            }
            for(int j = max_base; j >= 0; j--)
            {
                if(x>>j&1)
                {
                    if(!val[i][j])
                    {
                        val[i][j] = x;
                        pos[i][j] = p;
                        break;
                    }
                    else
                    {
                        if(pos[i][j] < p) swap(val[i][j], x),swap(pos[i][j], p);
                        x ^= val[i][j];
                    }
                }
            }
        }
        for(int i = 1; i <= q; i++)
        {
            cin >> op;
            if(op)
            {
                cin >> x;
                x ^= last;
                a[++n] = x, p = n;
                for(int j = max_base; j >= 0; j--)
                {
                    val[n][j] = val[n-1][j];
                    pos[n][j] = pos[n-1][j];
                }
                for(int j = max_base; j >= 0; j--)
                {
                    if(x>>j&1)
                    {
                        if(!val[n][j])
                        {
                            val[n][j] = x;
                            pos[n][j] = p;
                            break;
                        }
                        else
                        {
                            if(pos[n][j] < p) swap(val[n][j], x),swap(pos[n][j], p);
                            x ^= val[n][j];
                        }
                    }
                }
            }
            else
            {
                cin >> l >> r;
                l = (l ^ last) % n + 1;
                r = (r ^ last) % n + 1;
                if(l > r) swap(l, r);//!!
                int ans = 0;
                for(int j = max_base; j >= 0; j--)
                    if(pos[r][j] >= l && val[r][j])
                        ans = max(ans, ans^val[r][j]);
                last = ans;
                printf("%d\n", ans);
            }
        }
    }
    return 0;
}


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值