Binary

Description

这里写图片描述

Data Constraint

这里写图片描述

Solution

这道题部分分很好的提示了我们该怎么做。对于另外20%的数据,x=0的情况,很显然要把每个数按二进制一位一位拆开来做。因为and运算是每一位独立的,注意到ai,x,y< 220 ,所以我们可以开个数组(F[0..20])存每一个二进制位1的个数,那么对于每个询问,如果y在二进制下第i位是1,答案就加上F[i]* 2i1
那么这该怎么拓展到全部数据呢。我们开个树状数组Tri[i][j],i:1~20,表示每个二进制位的树状数组,j表示的是每个数mod 2i (即每个数二进制下后i位),树状数组存的就是j出现的次数。每次修改就把a[x]对应的都-1,y的+1。而询问,如果y在二进制下第i位是1,那么对于Tri[i][j],我们要查询的j就是[L,R],L= 2i1 -xR= 2i -1-x,这里的x是mod了 2i 的,因为L有可能小于零,所以L=(L+ 2i ) mod 2i ,而这样一来,L就有可能大于R了。当L<=R,Ans=Ans+(Find(i,R)-Find(i,L-1)) * 2i1 ;当L>R,Ans=Ans+(Find(i,R)+Find(i, 2i )-Find(i,L-1)) * 2i1 。然后就可以了。

Code

Const
    Maxn=100005;
    Num=1100000;

Var
    n,m:Longint;
    a:Array[0..Maxn] OF Longint;
    f:Array[0..20,0..Num] OF Int64;

Function Lowbit(x:Longint):Longint;
Begin
    Exit(x And (-x));
End;

Procedure Inse(k,x:Longint);
Var
    Mx:Longint;
Begin
    Mx:=1 << k;
    While x<=Mx Do
    Begin
        Inc(f[k][x]); Inc(x,Lowbit(x));
    End;
End;

Procedure Init();
Var
    i,j:Longint;
Begin
    Readln(n,m);
    For i:=1 To n Do
    Begin
        Read(a[i]);
        For j:=1 To 20 Do Inse(j,a[i] Mod (1 << j)+1);
    End;
End;

Procedure Dele(k,x:Longint);
Var
    Mx:Longint;
Begin
    Mx:=1 << k;
    While x<=Mx Do
    Begin
        Dec(f[k][x]); Inc(x,Lowbit(x));
    End;
End;

Procedure Change(x,y:Longint);
Var
    i:Longint;
Begin
    For i:=1 To 20 Do
    Begin
        Inse(i,y Mod (1 << i)+1); Dele(i,a[x] Mod (1 << i)+1);
    End;
    a[x]:=y;
End;

Function Find(k,x:Longint):Int64;
Begin
    Find:=0;
    While x>0 Do
    Begin
        Inc(Find,f[k][x]); Dec(x,Lowbit(x));
    End;
End;

Function Get(x,y:Longint):Int64;
Var
    i,l,r,t,Mo:Longint;
    Tot:Int64;
Begin
    Get:=0;
    For i:=1 To 20 Do
    Begin
        If y And (1 << (i-1))=0 Then Continue;
        Mo:=1 << i; t:=x Mod Mo;
        l:=(1 << (i-1)-t+Mo) Mod Mo; r:=Mo-1-t;
        Tot:=Find(i,r+1)-Find(i,l);
        If Tot<0 Then Tot:=Tot+Find(i,Mo);
        Get:=Get+Tot*(1 << (i-1));
    End;
End;

Procedure Main();
Var
    k,x,y:Longint;
Begin
    For m:=m Downto 1 Do
    Begin
        Readln(k,x,y);
        If k=1 Then Change(x,y) Else Writeln(Get(x,y));
    End;
End;

Begin
    //Assign(Input,'binary.in'); Reset(Input);
    //Assign(Output,'binary.out'); Rewrite(Output);

    Init();
    Main();

    //Close(Input); Close(Output);
End.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值