Description
给定一个长度为n的整数数列
a
a
和 次操作:
修改操作:形如
1 x y
1
x
y
,表示将
ax
a
x
的值改为
y
y
;
询问操作:形如
2 x y
2
x
y
,表示询问
∑ni=1(ai+x) and y
∑
i
=
1
n
(
a
i
+
x
)
a
n
d
y
的值。
Input
第一行两个整数
n,q
n
,
q
。
第二行包含n个整数
ai
a
i
。
之后
q
q
行包含三个整数
opt,x,y
o
p
t
,
x
,
y
。
Output
对于每一个询问操作,输出一行包含一个整数,表示该询问操作的答案。
Data Constraint
n,q≤1000000≤ai,x,y<220 n , q ≤ 100000 0 ≤ a i , x , y < 2 20
Sample Input
6 6
8 9 1 13 9 3
1 4 5
2 6 9
1 3 7
2 7 7
1 6 1
2 11 13
Sample Output
45
19
21
Solution
①当 x=0 x = 0 时
将每一项
ai
a
i
拆分成二进制,记录每一位(即
ai and 2i
a
i
a
n
d
2
i
)
=1
=
1
的数有多少个,
如果该位如果
y
y
的第
2i
2
i
位也正好等于
1
1
,那么将
ans
a
n
s
加
fi∗2i
f
i
∗
2
i
。
②当 x≠0 x ≠ 0 时
还是一位一位增加答案,假设现考虑第i位,则显然是
[2i , 2i+1−1]
[
2
i
,
2
i
+
1
−
1
]
的数是可行的,
所以我们可以建立树状数组
ci,j
c
i
,
j
来记录每项
a mod 2i+1
a
m
o
d
2
i
+
1
,但还是要对x进行讨论:
姑且将
x mod 2i+1
x
m
o
d
2
i
+
1
先。
<1>当 x≤ 2i x ≤ 2 i 时
ans a n s 加在 [2i−x , 2i+1−1−x] [ 2 i − x , 2 i + 1 − 1 − x ] 之间的数的个数 ∗2i ∗ 2 i 。
<2>当 x>2i x > 2 i 时
ans a n s 加在 [0 , 2i+1−1−x] ⋃ [2i+1+2i−x,2i+1−1] [ 0 , 2 i + 1 − 1 − x ] ⋃ [ 2 i + 1 + 2 i − x , 2 i + 1 − 1 ] 之间的数的个数 ∗2i ∗ 2 i 。
code
const maxn=100005;
w=20;
mm=1<<20;
var i,j,n,q,o,x,x0,y:longint;
ans,v:int64;
a:array[1..maxn] of longint;
c:array[1..20,0..1200000] of int64;
procedure update(i,value,mo:longint);
begin
if i=0 then c[mo,i]:=c[mo,i]+value else
while(i<=mm) do begin
c[mo,i]:=c[mo,i]+value;
i:=i+i and (-i);
end;
end;
function get(i,mo:longint):int64;
var s:int64;
begin
s:=0;
while i>0 do begin
s:=s+c[mo,i];
i:=i-i and (-i);
end;
if i>=0 then s:=s+c[mo,0];
exit(s);
end;
begin
readln(n,q);
for i:=1 to n do read(a[i]);
readln;
for i:=1 to w do
for j:=1 to n do update(a[j] mod (1<<i),1,i);
for i:=1 to q do begin
readln(o,x0,y);
if o=1 then begin
for j:=1 to w do update(a[x0] mod (1<<j),-1,j);
a[x0]:=y;
for j:=1 to w do update(a[x0] mod (1<<j),1,j);
end else begin
ans:=0;
for j:=1 to w do if y>>(j-1) mod 2=1 then begin
x:=x0 mod (1<<j);
if x<=1<<(j-1) then begin
v:=get(1<<j-1-x,j);
v:=v-get(1<<(j-1)-x-1,j);
v:=v*(1<<(j-1));
ans:=ans+v;
end else begin
v:=get(1<<j-1-x,j);
v:=v+get(1<<j-1,j);
v:=v-get((1<<j)+(1<<(j-1))-x-1,j);
v:=v*(1<<(j-1));
ans:=ans+v;
end;
end;
writeln(ans);
end;
end;
end.