2019 multi university training contest 1 - Operation (interval linear basis)

Keywords: PHP

Original title: http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1002&cid=848

Title:

Give an array of n numbers with two operations

  1. Select some numbers in [l,r][l,r][l,r] to maximize exclusive or and output the maximum value;
  2. Insert a number after the array.

Analysis:

If you choose some numbers with the largest exclusive or, then there is no doubt that they are linear bases. Students who don't know linear basis can have a look My blog.

We consider maintaining 31 base positions to the left of each position. Suppose I already know the positions and values of 31 bases I − 1i-1i − 1 to the left. When maintaining iii, 31 bases are maintained from high to low.

  • If this base has not appeared before, select the current number as the base of this bit.
  • If so, compare positions. Because when we set RRR to query, the more right the base is, the more likely it will fall into my range. So we will base on the right, XOR the value on the left, and then update it.

Code:

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rrep(i,a,b) for(int i=a;i>=b;i--)
const int maxn=1e6+5;
int ji[maxn][31];
int pos[maxn][31];

void deal(int n,int val){
    int nex=n;
    rep(i,0,30)ji[n][i]=ji[n-1][i],pos[n][i]=pos[n-1][i];
    rrep(i,30,0){
        if(val&(1<<i)){
            if(!ji[n][i]){
                ji[n][i]=val;pos[n][i]=nex;return;
            }
            if(pos[n][i]<nex){
                swap(val,ji[n][i]);
                swap(nex,pos[n][i]);
            }
            val^=ji[n][i];
        }
    }
}

int main(){
    int t;scanf("%d",&t);
    while(t--){
        int lst=0;
        int n,m;scanf("%d%d",&n,&m);
        rep(i,1,n){
            int val;scanf("%d",&val);
            deal(i,val);
        }
        while(m--){
            int f;scanf("%d",&f);
            if(f==1){
                int val;scanf("%d",&val);
                val^=lst;
                deal(++n,val);
            }
            else{
                int l,r;scanf("%d%d",&l,&r);
                l^=lst,r^=lst;
                l%=n,r%=n;
                l++,r++;
                if(l>r)swap(l,r);

                int ans=0;
                rrep(i,30,0){
                    if(pos[r][i]>=l){
                        if((ans^ji[r][i])>ans){
                            ans^=ji[r][i];
                        }
                    }
                }
                printf("%d\n",ans);
                lst=ans;
            }
        }
    }
}

Posted by afterburner on Fri, 18 Oct 2019 14:34:26 -0700