P11071 QMSOI R1 Distorted Fate 题解

P11071 QMSOI R1 Distorted Fate

对于一个序列支持区间异或\(x\),查询区间内所有前缀按位或的值求和 \((n,q\le 2\times 10^5,0\le a_i,x\le 2^{30})\)

\(sol\) :考虑拆位,每一位开一颗线段树,维护区间是否有 \(1/0\) ,异或时交换,查询时线段树上二分,求区间内第一个 \(1\) 的位置 \(x\) ,则有 \(r-x+1\) 个前缀对答案有贡献 ,因为每一位时独立的,可以把询问离线下来,每一位单独计算贡献。

\(code\) :

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll N=2e5+5,mod=(1<<30);
ll n,k,ans[N],a[N],t,v;
struct node{int opt,l,r,x;}q[N];
bool tr[N<<3][3];
template <typename T> inline void read(T &x) {
	x = 0; int f = 1; char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -1;
	for (; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
	x *= f;
}
void upd(int x)
{
	tr[x][0]=tr[x<<1][0]||tr[x<<1|1][0];
	tr[x][1]=tr[x<<1][1]||tr[x<<1|1][1];
}
void pd(int x)
{
	if(!tr[x][2]) return;
	swap(tr[x<<1][0],tr[x<<1][1]);
	swap(tr[x<<1|1][0],tr[x<<1|1][1]);
	tr[x<<1][2]=!tr[x<<1][2];
	tr[x<<1|1][2]=!tr[x<<1|1][2];
	tr[x][2]=0;
}
void build(int x,int l,int r)
{
	if(l==r)
	{
		tr[x][2]=0;
		tr[x][1]=(a[l]&v);
		tr[x][0]=!tr[x][1];
		return ;
	}
	int mid=l+r>>1;
	build(x<<1,l,mid);
	build(x<<1|1,mid+1,r);
	upd(x);
}
void modify(int x,int l,int r,int lt,int rt)
{
	if(l>=lt&&r<=rt) 
	{
		swap(tr[x][0],tr[x][1]);
		tr[x][2]=!tr[x][2];
		pd(x);
		return ;
	}
	int mid=l+r>>1;
	pd(x);
	if(lt<=mid) modify(x<<1,l,mid,lt,rt);
	if(rt>mid) modify(x<<1|1,mid+1,r,lt,rt);
	upd(x);
}
node query(int x,int l,int r,int lt,int rt)
{
	if(l>=lt&&r<=rt) return {tr[x][1],l,r,x};
	int mid=l+r>>1;
	pd(x);
	node res={0,0,0,0};
	if(mid>=lt&&tr[x<<1][1]) res=query(x<<1,l,mid,lt,rt);
	if(mid<rt&&!res.opt) res=query(x<<1|1,mid+1,r,lt,rt);
	upd(x);
	return res;
}
int que(int x,int l,int r)
{
	if(l==r) return l;
	pd(x);
	int mid=l+r>>1;
	if(tr[x<<1][1]) return que(x<<1,l,mid);
	else return que(x<<1|1,mid+1,r);
}
int main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++) read(a[i]);
	for(int i=1;i<=k;i++)
	{
		read(q[i].opt),read(q[i].l),read(q[i].r);
		if(q[i].opt==1) read(q[i].x);
	}
	for(t=0;t<=30;t++)
	{
		v=(1<<t);
		memset(tr,0,sizeof tr);
		build(1,1,n);
		if(tr[1][1]==0) break;
		for(int i=1;i<=k;i++)
		{
			int opt=q[i].opt,l=q[i].l,r=q[i].r,x=q[i].x;
			if(opt==1&&((x&v)!=0))
				modify(1,1,n,l,r);
			if(opt==2)
			{
				node s=query(1,1,n,l,r);
				int k=s.opt?que(s.x,s.l,s.r):(r+1);
				ans[i]+=(ll)(r-k+1)*v;
			}
		}
	}
	for(int i=1;i<=k;i++)
		if(q[i].opt==2) printf("%lld\n",ans[i]%mod);
	return 0;
}
posted @ 2024-12-19 14:33  Re_Star  阅读(61)  评论(0)    收藏  举报