[HDU 6579]Operation

题目链接: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 &lt; l 1 r_1&lt;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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值