[bzoj1273] [BeiJingWc2008]序列

本文介绍了一种使用位运算处理查询问题的算法实现方法。通过维护不同长度的后缀,并利用前缀和技巧来高效地计算特定条件下的数值范围查询。

  一开始想拆位。。但显然没法应对进位啊什么的。

  所以维护每一个长度的后缀。

  查询有多少个a&2^i>0,也就是长度为(i+1)的后缀里,值为2^i...2^(i+1)-1的数有多少个。

  前缀和一波就好了。。整体加就开个变量记着,查询的时候再分一下类。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #define ll long long
 5 using namespace std;
 6 const int maxn=100233;
 7 int sm[17][1<<16|1],a[maxn];
 8 int add[17],one[17];
 9 int i,j,k,n,m,L,R,SM;
10 ll ans;
11  
12 int ra;char rx;
13 inline int read(){
14     rx=getchar(),ra=0;
15     while(rx<'0'||rx>'9')rx=getchar();
16     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
17 }
18 int main(){
19     n=read(),m=read();register int j;
20     for(i=1;i<=n;i++)a[i]=read();
21     for(i=1;i<=16;i++)one[i]=one[i-1]<<1|1;
22     for(i=1;i<=16;i++){
23         for(j=1;j<=n;j++)sm[i][a[j]&one[i]]++;
24         for(j=1;j<=one[i];j++)sm[i][j]+=sm[i][j-1];
25     }char s[2];int x;
26     while(m--){
27         scanf("%s",s);x=read();
28         if(s[0]=='A')for(i=1;i<=16;i++)add[i]+=x&one[i],add[i]&=one[i];
29         else
30             x++,L=(1<<(x-1))-add[x],R=one[x]-add[x],SM=0,
31             ans+=L>=0?(sm[x][R]-(!L?0:sm[x][L-1])):(sm[x][R]+sm[x][one[x]]-sm[x][L+(1<<x)-1]);
32     }
33     printf("%lld\n",ans);
34 }
35 
View Code

 

转载于:https://www.cnblogs.com/czllgzmzl/p/5623413.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值