题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6579
题面
大意
给出一个长为
n
n
n的数组
a
[
]
a[]
a[],及
m
m
m个操作。
操作分为两类:
- 0 0 0 l l l r r r 输出从 a l a_l al~ a r a_r ar取出若干个数可得的异或值的最大值
-
1
1
1
x
x
x 将
n
n
n+1,并使
a
n
=
x
a_n=x
an=x
同时题目要求强制在线
若操作为查询,则 l 1 l_1 l1=( l l l^lastans)mod n+1, r 1 r_1 r1=( r r r^lastans)mod n+1,若 r 1 < l 1 r_1<l_1 r1<l1则交换 r 1 , l 1 r_1,l_1 r1,l1实际查询区间为 [ l 1 , r 1 ] [l_1,r_1] [l1,r1]
若操作为添加,则实际添加的值为( x x x^lastans)
其中lastans为最后一次输出的数值(一开始为0)
思路
就是区间线性基,与[UVALive 8512]类似,可以参考我的另一篇博客
https://blog.csdn.net/weixin_44582673/article/details/99080121
有关于区间线性基以及[UVALive 8512]的详细解释。
AC代码
一开始全开long long MLE是真的要命
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<stdlib.h>
#include<string.h>
using namespace std;
typedef long long ll;
typedef struct L_B
{
#define NUM 31
private:
int b[NUM+5],cnt,pos[NUM+5];
public:
void push_down(ll now,ll pt,ll o_pos)
{
for(ll i=pt;i>=0;i--)
{
if(now&(1ll<<i))
if(this->b[i])
{
if(this->pos[i]<o_pos)
{
push_down(this->b[i]^now,i-1,pos[i]);
this->b[i]=now;pos[i]=o_pos;return;
}else now^=this->b[i];
}else
{
this->b[i]=now;this->pos[i]=o_pos;return;
}
}
}
void insert(ll now,ll t)//插入
{
for(int i=NUM;i>=0;--i)
{
if(now&(1ll<<i))
if(this->b[i])
{
push_down(this->b[i]^now,i-1,this->pos[i]);
this->b[i]=now;this->pos[i]=t;return;
}
else
{
this->b[i]=now;this->pos[i]=t;return;
}
}
return;
}
void clear()
{
for(ll i=0;i<NUM;i++)this->b[i]=0;
}
void rebuild()//重构
{
for(int i=1;i<=NUM;i++)
if(this->b[i])
{
for(int j=0;j<i;j++)
{
if(this->b[i]&(1ll<<j))
this->b[i]^=this->b[j];
}
}
return;
}
ll get_max(ll now,ll l)//取最大值
{
ll ret=now;
for(int i=NUM;i+1;--i)
{
if(this->pos[i]>=l)
if((ret^this->b[i])>ret)ret^=this->b[i];
}
return ret;
}
#undef NUM
} L_B;
ll n,q,qu,t,k,l,r,op,x,ans;
L_B B[1000005];
ll find(ll l,ll r,ll k)
{
L_B temp=B[r];
return temp.get_max(k,l);
}
int main()
{
scanf("%lld",&t);
while(t--)
{
memset(B+1,0,n*sizeof(L_B));ans=0;
scanf("%lld%lld",&n,&q);
for(ll i=1;i<=n;i++)
{
scanf("%lld",&x);
B[i]=B[i-1];B[i].insert(x,i);
}
for(ll i=1;i<=q;i++)
{
scanf("%lld",&op);
if(op==0)
{
scanf("%lld%lld",&l,&r);l=(l^ans)%n+1;r=(r^ans)%n+1;
if(l>r)swap(l,r);
printf("%lld\n",ans=find(l,r,(long long)0));
}
else
{
scanf("%lld",&x);n++;B[n]=B[n-1];x^=ans;
B[n].insert(x,n);
}
}
}
return 0;
}