#4706. 异或
程序员文章站
2022-07-15 12:06:04
...
题目描述
题解
考虑答案转化为两个前缀和相减,也就是求
考虑最高位,如果 在第 位是 的话,那就变成 或 , 是去掉第 位的值
如果 在第 位是 的话,那有 和 两个范围,其中前面区间和 异或肯定还是这个区间内的取值,另一边递归往下做就好了
所以我们现在有 ,如何求
考虑把 排序,然后在每个 预处理出一个答案,然后我们只要二分到最后一个小于等于 的 即可
效率:
代码
#include <bits/stdc++.h>
#define _(d) while(d(isdigit(c=getchar())))
using namespace std;
int R(){char c;_(!);int x=(c^48);_()x=(x<<3)+(x<<1)+(c^48);return x;}
int ww[20];
void W(int x){
if (!x){putchar(48);return;}
int v=0;while(x) ww[++v]=x%10,x/=10;
for (int i=v;i;i--) putchar(ww[i]^48);
}
const int N=1e5+5,P=998244353;
int n,q,a[N],b[N],B,s[N];
int X(int x){return x>=P?x-P:x;}
int qry(int x){
int v=upper_bound(b+1,b+B+1,x)-b-1;
if (!v) return 0;
int u=upper_bound(a+1,a+n+1,x)-a-1;
return X(s[v-1]+1ll*u*u%P*(x-b[v]+1)%P);
}
int qry(int m,int x){
if (m<0) return 0;int v=0,w=0;
for (int u,y,i=29;~i;i--){
y=(1<<i);u=(x&y);
if ((m>>i)&1){
v=X(v+X(qry((w|u)+y-1)-qry((w|u)-1)+P));
w|=(y^u);
}
else w|=u;
}
return X(v+X(qry(w)-qry(w-1)+P));
}
int main(){
n=R();q=R();
for (int i=1;i<=n;i++)
b[++B]=a[i]=R();
sort(a+1,a+n+1);sort(b+1,b+n+1);
B=unique(b+1,b+B+1)-b-1;
for (int v,i=1;i<B;i++){
v=upper_bound(a+1,a+n+1,b[i])-a-1;
s[i]=X(s[i-1]+1ll*(b[i+1]-b[i])*v%P*v%P);
}
for (int l,r,x;q--;)
l=R(),r=R(),x=R(),
W(X(qry(r,x)-qry(l-1,x)+P)),putchar('\n');
return 0;
}
上一篇: 异或的性质及应用