題目大意
【40%】n,q<=5000
【另20%】所有詢問的x=0
【100%】n,q<=10^5
代碼
//我把線段樹換成樹狀數組,這樣常數小代碼短
#include<cstdio>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long LL;
const int maxn=(1e5)+5, MX=20, maxc=(1<<20)+5;
int n,a[maxn],er[MX+5];
int c[MX+2][maxc];
int lowbit(int x) {return x&(-x);}
void xg(int ty,int x,int z)
{
if (x==0) {c[ty][0]+=z; return;}
for(; x<er[ty]; x+=lowbit(x)) c[ty][x]+=z;
}
int get(int ty,int x)
{
if (x<0) return 0;
int re=0;
for(; x; x-=lowbit(x)) re+=c[ty][x];
return re+c[ty][0];
}
int q;
int main()
{
fo(i,0,MX) er[i]=1<<i;
scanf("%d %d",&n,&q);
fo(i,1,n)
{
scanf("%d",&a[i]);
fo(j,1,20) xg(j,a[i]%er[j],1);
}
while (q--)
{
int ty,x,y;
scanf("%d %d %d",&ty,&x,&y);
if (ty==1)
{
fo(i,1,20) xg(i,a[x]%er[i],-1);
fo(i,1,20) xg(i,y%er[i],1);
a[x]=y;
} else
{
LL ans=0;
fo(i,1,MX) if (y&er[i-1])
{
int xx=x%er[i], st=er[i-1]-xx, en=er[i]-1-xx;
if (st<0)
{
ans+=(LL)er[i-1]*get(i,en);
if (i>1) ans+=(LL)er[i-1]*(get(i,er[i]-1)-get(i,er[i]+st-1));
} else
{
ans+=(LL)er[i-1]*(get(i,en)-get(i,st-1));
}
}
printf("%lld\n",ans);
}
}
}