求异或第k小
/*
**author:revolIA
*submit:
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxbit = 63;
ll bit[maxbit],Lbit[maxbit];
int main(){
int t,Case = 0,n,m;
scanf("%d",&t);
while(t--){
memset(bit,0,sizeof bit),m = 0;//初始化or清空
printf("Case #%d:\n",++Case);
scanf("%d",&n);
for(int i=0;i<n;i++){
ll x;
scanf("%lld",&x);
for(int j=maxbit-1;~j;j--)if((x>>j)&1){//插入
if(!bit[j]){
bit[j] = x;
break;
}
x ^= bit[j];
}
}
for(int i=maxbit-1;~i;i--){// 类似高斯消元
for(int j=i+1;j<maxbit;j++){
if((bit[j]>>i)&1)
bit[j] ^= bit[i];
}
}
for(int i=0;i<maxbit;i++)if(bit[i])
Lbit[m++] = bit[i];
int q;
scanf("%d",&q);
while(q--){
ll k;
scanf("%lld",&k);
if(n != m)// 0
k--;
if(k >= 1ll<<m){// 线性基最多表示多少个数
printf("-1\n");
continue;
}
ll ans = 0;
for(int i=0;i<maxbit;i++)if((k>>i)&1)
ans ^= Lbit[i];
printf("%lld\n",ans);
}
}
return 0;
}
题意:
给一个长度n的数组,m次操作
操作:
0,询问异或最大值
1,在数组最后添加一个数x
强制在线
所以,l,r,x,都要异或上一次的答案
即
解:
处理一个 持久化的(前缀) 维护线性基内元素 当前位置向左第一次出现的位置(拗口、、)
如果不强制在线的话大概可以回滚莫队莽一下
/*
**author:revolIA
*submit:
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxbit = 31,maxn = 1e6+7;
int bit[maxn][maxbit],pos[maxn][maxbit];
void Add(int i,int x){
int k = i;
for(int j=maxbit-1;~j;j--)
bit[i][j] = bit[i-1][j],pos[i][j] = pos[i-1][j];
for(int j=maxbit-1;~j;j--)if((x>>j)&1){
if(!bit[i][j]){
bit[i][j] = x;
pos[i][j] = k;
break;
}
if(k>pos[i][j]){
swap(k,pos[i][j]);
swap(x,bit[i][j]);
}
x ^= bit[i][j];
}
}
int main(){
int t,n,q;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&q);
for(int i=1,x;i<=n;i++)scanf("%d",&x),Add(i,x);
int ans = 0;
while(q--){
int op,l,r;
scanf("%d",&op);
if(op){
scanf("%d",&l);
Add(++n,l^ans);
}else{
scanf("%d%d",&l,&r);
l = (l^ans)%n+1,r = (r^ans)%n+1;
if(l>r)swap(l,r);
ans = 0;
for(int j=maxbit-1;~j;j--)if(pos[r][j]>=l)
ans = max(ans,ans^bit[r][j]);
printf("%d\n",ans);
}
}
for(int i=1;i<=n;i++)for(int j=0;j<maxbit;j++)
bit[i][j] = pos[i][j] = 0;
}
return 0;
}