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.
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 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; }
路漫漫其修远兮,吾将上下而求索