P11071 「QMSOI R1」 Distorted Fate题解

题意:
给定一个序列,给定两种操作:

  1. 将一个区间异或上一个给定的值。

  2. 给定 l,r

(i=lrj=liAj)mod230

0ai,x<2301lrn

思路

  • 由于操作数以及区间过大,一位一位地去模拟肯定是不行的。因此考虑去离线下来拆位,对于每一个操作的每一位单独维护贡献。

  • 由于是前缀或,因此对于每一位而言,只要有一个数在这一位上是1,那后面的所有值也一定都是1。
    因此问题就转化成了维护区间第一个1所在的位置,答案就是这个位置与右端点的距离。

  • 考虑如何去维护这个东西。显然去查找不可能直接找,需要去二分。但同时还要维护操作1,因此考虑用线段树去维护。
    那怎么在线段树上查找呢?考虑维护节点所代表的区间是不是全为零,如果全为零的话就向右儿子搜,否则向左儿子搜。
    但由于异或操作,还可以维护一个是否全是1方便修改。需要修改的时候将两个标记交换就可以了。

code

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int p=1073741824;
const int N=2e5+7;
int n,m,a[N],loc;bool s1[N<<2],s2[N<<2],b[N],sign,tag[N<<2];
struct ques
{
	int opt,l,r,x;long long ans=0;
}q[N];
#define ls (u<<1)
#define rs ((u<<1)|1)
void push_up(int u)
{
	s1[u]=s1[ls]|s1[rs];s2[u]=s2[ls]|s2[rs];
}
void push_down(int u)
{
	if(!tag[u]) return;
	swap(s1[ls],s2[ls]),swap(s1[rs],s2[rs]);
	tag[ls]^=1,tag[rs]^=1;
	tag[u]=0;
}
void build(int u,int l,int r)
{
	tag[u]=0;if(l==r){s1[u]=b[l],s2[u]=b[l]^1;return;}
	int mid=(l+r)>>1;build(ls,l,mid);build(rs,mid+1,r);
	push_up(u);
}
void modify(int u,int l,int r,int ql,int qr)
{
	if(l>=ql&&r<=qr) {swap(s1[u],s2[u]),tag[u]^=1;return;}
	int mid=(l+r)>>1;push_down(u);
	if(mid>=ql) modify(ls,l,mid,ql,qr);if(mid<qr) modify(rs,mid+1,r,ql,qr);
	push_up(u);
}
void query(int u,int l,int r,int ql,int qr)
{
	if((!s1[u])||sign||r<ql||l>qr) return;
	if(l==r) {if(s1[u]&&l<loc&&l>=ql)loc=l,sign=1;return;}
	int mid=(l+r)>>1;push_down(u);
	if(mid>=ql) query(ls,l,mid,ql,qr);
	if(sign) return;
	if(mid<qr) query(rs,mid+1,r,ql,qr);
}
int main()
{
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=m;i++) {cin>>q[i].opt>>q[i].l>>q[i].r;if(q[i].opt==1) cin>>q[i].x;}
	for(int k=0;k<=30;k++)
	{
		for(int i=1;i<=n;i++) b[i]=(a[i]>>k)&1;build(1,1,n);
		for(int i=1;i<=m;i++)
		{
			if(q[i].opt==1) {if(((q[i].x>>k)&1)==1) modify(1,1,n,q[i].l,q[i].r);}
			else
			{
				sign=0;loc=q[i].r+1;query(1,1,n,q[i].l,q[i].r);
				q[i].ans=(q[i].ans+1ll*(q[i].r-loc+1ll)*(1ll<<k)%p)%p;
			}
		}
	}
	for(int i=1;i<=m;i++) if(q[i].opt==2) cout<<q[i].ans<<'\n';
	return 0;
}
posted @   all_for_god  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验
点击右上角即可分享
微信分享提示