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;
}

浙公网安备 33010602011771号