[模板] 线段树维护区间线性基

59 篇文章 0 订阅
51 篇文章 1 订阅

单纯放个代码,可能以后用的到…
实际上是写了个这玩意疯狂MLE

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
const int maxm=1e5+100;
int n,m,tot;
int val[maxm];
struct node{
	int p[33];
	inline void clear(){memset(p,0,sizeof(p));}
	inline void insert(int x)
	{
		for(int i=31;i>=0;i--)
		{
			if(!p[i])
			{
				p[i]=x;
				return;
			}
			x^=p[i];
		}
	}
	inline int ask()
	{
		int res=0;
		for(int i=31;i>=0;i--) res=std::max(res,res^p[i]);
	} 
};
struct tree{
	node tag[maxm*2],ans;
	inline void merge(node &x,node &y)
	{
		for(int i=31;i>=0;i--) if(x.p[i]) y.insert(x.p[i]);
	}
	inline void pushup(int o)
	{
		merge(tag[(o<<1)],tag[o]);
		merge(tag[(o<<1)|1],tag[o]);
	} 
	inline void clear(){memset(tag,0,sizeof(tag));}
	void insert(int o,int l,int r,int ind,int x)
	{
		if(l>=r)
		{
			tag[o].clear();
			tag[o].insert(x);
			return;
		}
		int mid=(l+r)>>1;
		ind<=mid?insert((o<<1),l,mid,ind,x):insert((o<<1)|1,mid+1,r,ind,x);
		pushup(o);
	}
	void build(int o,int l,int r)
	{
		if(l>=r)
		{
			tag[o].insert(val[l]);
			return;
		}
		int mid=(l+r)>>1;
		build((o<<1),l,mid),build((o<<1)|1,mid+1,r);
		pushup(o);
	}
	void ask(int o,int l,int r,int ql,int qr)
	{
		if((l<=ql)&&(r<=qr))
		{
			merge(tag[o],ans);
			return;
		}
		int mid=(l+r)>>1;
		if(ql<=mid) ask((o<<1),l,mid,ql,qr);
		if(qr>mid) ask((o<<1)|1,mid+1,r,ql,qr);
	}
}st;
inline void work()
{
	st.clear();
    scanf("%d%d",&n,&m);
    int last=0;
    int tot=n+m;
    for(int i=1;i<=n;i++) scanf("%d",&val[i]);
    st.build(1,1,tot);
    for(int i=1;i<=m;i++)
    {
    	int opt,l,r;
    	scanf("%d%d",&opt,&l);
    	if(opt==0)
    	{
    		scanf("%d",&r);
    		l=(l^last)%n+1;
    		r=(r^last)%n+1;
    		if(l>r) std::swap(l,r);
    		printf("%d %d\n",l,r);
    		st.ans.clear();
    		st.ask(1,1,tot,l,r);
    		last=st.ans.ask();
    		printf("%d\n",last);
		}
		else
		{
			val[++n]=l^last;
			st.insert(1,1,tot,n,val[n]);
		}
	}
}
int main()
{
	int t;
	scanf("%d",&t);
	for(int i=1;i<=t;i++) work();
	return 0; 
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值