Rt,用的是题解里的做法,就是一个 trie 和一个按位前缀和分别维护有序段和无序段,但是仅仅过了样例,求大佬帮忙调一下
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,Xor,triexor;
int node,trie[6000005][2],num[6000005],val[6000005][32];
int cnt,a[200005],sum[200005][30];
void insert_end(int x)
{
cnt++;
a[cnt]=x;
for(int i=0;i<=29;i++) sum[cnt][i]=sum[cnt-1][i]+((x>>i)&1);
return ;
}
void insert_trie(int x)
{
int rt=0;
num[0]++;
for(int i=29;i>=0;i--)
{
int now=(x>>i)&1;
if(!trie[rt][now]) trie[rt][now]=++node;
rt=trie[rt][now];
for(int j=29;j>=0;j--)
val[rt][j]+=(x>>j)&1;
num[rt]++;
}
return ;
}
long long query_trie(int x)
{
if(x==0) return 0;
int rt=0,valx=0;
long long res=0;
for(int i=29;i>=0;i--)
{
int b=(Xor>>i)&1;
if(x<=num[trie[rt][b]]) rt=trie[rt][b],valx+=b<<i;
else
{
x-=num[trie[rt][b]];
for(int j=29;j>=0;j--)
if((triexor>>j)&1)
res+=(long long)(num[trie[rt][b]]-val[trie[rt][b]][j])<<j;
else res+=(long long)val[trie[rt][b]][j]<<j;
rt=trie[rt][b^1];
valx+=(b^1)<<i;
}
}
return res+(valx^triexor)*x;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
insert_end(x);
}
scanf("%d",&m);
while(m--)
{
int op;
scanf("%d",&op);
if(op==1)
{
int x;
scanf("%d",&x);
insert_end(x^Xor);
}
else if(op==2)
{
int l,r;
scanf("%d%d",&l,&r);
long long res=0;
if(l<=num[0]) res=query_trie(min(num[0],r))-query_trie(l-1);
if(r>num[0])
{
int l1=max(1,l-num[0]),r1=r-num[0];
for(int i=29;i>=0;i--)
{
if((Xor>>i)&1)
res+=(long long)(r1-l1+1-sum[r1][i]+sum[l1-1][i])<<i;
else res+=(long long)(sum[r1][i]-sum[l1-1][i])<<i;
}
}
printf("%lld\n",res);
}
else if(op==3)
{
int x;
scanf("%d",&x);
Xor^=x;
}
else
{
for(int i=1;i<=cnt;i++) insert_trie(a[i]);
cnt=0;triexor=Xor;
}
}
return 0;
}