思路:考虑pow(2,k)对答案,应该为k+1位,此位不会对答案产生影响,于是,对于x和a[i],取k;
if(y>>k是1,那么pow(2,k)到pow(2,k+1)-1的个数即为答案;
于是,广泛适用的答案同时在pow(2,k)-k到pow(2,k+1)-k-1和pow(2,k+1)-z,pow(2,k+2)-z-1的数量即为答案:
(开log pow(2,20)个树状数组(20个))
code:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=2e6+10;
int n,q,a[N],tr[20][N];
typedef long long LL;
inline int lowbit(int x){
return x&-x;
}
inline void add(int x,int v){
for(int i=0;i<20;i++){
int d=x&(1<<i+1)-1;
for(int j=d+1;j<=(1<<i+1);j+=lowbit(j)){
tr[i][j]+=v;
}
}
}
inline LL sum(int x,int k){
LL res=0;
int l=(1<<k)-x,r=(1<<k+1)-x;
l=max(l,0),r=max(r,1);
for(int i=l;i;i-=lowbit(i)) res-=tr[k][i];
for(int i=r;i;i-=lowbit(i)) res+=tr[k][i];
l=(1<<k+1)+(1<<k)-x,r=(1<<k+2)-x;
if(l>=(1<<k+1)) return res<<k;
r=min(r,1<<k+1);
for(int i=l;i;i-=lowbit(i)) res-=tr[k][i];
for(int i=r;i;i-=lowbit(i)) res+=tr[k][i];
return res<<k;
}
int main(){
cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>a[i];
add(a[i],1);
}
for(int i=1;i<=q;i++)
{
int k,x,y;
cin>>k>>x>>y;
if(k==1){
add(a[x],-1);
add(a[x]=y,1);
}else{
LL ans=0;
for(int i=0;i<20;i++){
if(y&1<<i){
ans+=sum(x&(1<<i+1)-1,i);
}
}
cout<<ans<<endl;
}
}
return 0;
}
完结撒花