[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
",ans);
34 }
35 
View Code
原文地址:https://www.cnblogs.com/czllgzmzl/p/5623413.html