[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