Description
Solution
遇到位运算直接拆位。
那么查询:如果
y
的第
我们对于一个二进制位
那么对于这题20个树状数组就解决了。
Solution
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 100001
#define ll long long
using namespace std;
ll a[N];
ll c[22][N*12];
int p[22];
int ff=0;
int lb(int x) {return (x&(-x));}
void change(int i,int k,int s,int lim)
{
while(k<=lim)
{
c[i][k]+=s;
k+=lb(k);
}
}
int sum(int i,int k)
{
int t=0;
while(k)
{
t+=c[i][k];
k-=lb(k);
}
return t;
}
int main()
{
freopen("binary.in","r",stdin);
freopen("binary.out","w",stdout);
p[0]=1;
fo(i,1,20) p[i]=p[i-1]*2;
int n,q;
cin>>n>>q;
fo(i,1,n)
{
scanf("%lld",&a[i]);
fo(j,0,19) change(j,a[i]%p[j+1]+1,1,p[j+1]+1);
}
int tmp=0;
while(q--)
{
int z,x,y;
scanf("%d %d %d",&z,&x,&y);
if(z==1)
{
fo(i,0,19)
{
change(i,a[x]%p[i+1]+1,-1,p[i+1]+1);
change(i,y%p[i+1]+1,1,p[i+1]+1);
}
a[x]=y;
}
else
{
ll ans=0;
fo(i,0,19)
if(y&p[i])
{
int mo=p[i+1];
int l=((p[i]-x)%mo+mo)%mo,r=((p[i+1]-1-x)%mo+mo)%mo;
if(l>r) ans+=(sum(i,r+1)+sum(i,mo+1)-sum(i,l))*1ll*p[i];
else ans+=(sum(i,r+1)-sum(i,l))*1ll*p[i];
}
printf("%lld\n",ans);
}
}
}