2020 CCPC-Wannafly Winter Camp Day6 (Div.1&2) H. 异或询问
思路: 根据异或的性质,可以把 ∑lri⊕x划分成一些连续的区间,对每个区间计算答案。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
int a[N],n,q;
int b[N];
LL sum[N];
int len;
LL qc[N];
const LL mod =998244353;
void init(){
sort(a+1,a+1+n);
for(int i=1;i<=n;i++)b[i]=a[i];
len=unique(b+1,b+1+n)-b-1;
for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+1+len,a[i])-b;
for(int i=1;i<=n;i++){
sum[a[i]]++;
}
for(int i=1;i<len;i++){
sum[i]=(0ll+sum[i-1]+sum[i])%mod;
qc[i]=(1ll*sum[i]*sum[i]%mod*(b[i+1]-b[i])%mod+qc[i-1])%mod;
}
sum[len]+=sum[len-1];
sum[len]%=mod;
}
LL f(int r){
int x=upper_bound(b+1,b+1+len,r)-b-1;
if(!x)return 0;
LL res=qc[x-1];
return (res+sum[x]*sum[x]%mod*(r-b[x]+1)%mod)%mod;
}
LL g(int l,int r){
return (f(r)-f(l-1)+mod)%mod;
}
LL get(int r,int x){
if(r<0)return 0;
LL tot=0;
int res=0;
for(int i=30;~i;i--){
if(r&(1<<i)){
if(!(x&(1<<i))){
tot+=g(res,res+(1<<i)-1);
res|=(1<<i);
}else{
tot+=g(res|(1<<i),(res|(1<<i))+(1<<i)-1);
}
}else{
if((1<<i)&x)res|=(1<<i);
}
tot%=mod;
}
tot+=g(res,res);
tot%=mod;
return tot;
}
int main() {
ios::sync_with_stdio(false);
cin>>n>>q;
for(int i=1;i<=n;i++)cin>>a[i];
init();
for(int i=1;i<=q;i++){
int l,r,x;
cin>>l>>r>>x;
cout<<(get(r,x)-get(l-1,x)+mod)%mod<<'\n';
}
return 0;
}