P9883题解

P9883题解

算法

  • \(c[]\) 其实就是树状数组,设其原数组是 \(a[]\)
  • 就是问 \(a[]\) 最少有多少非零位置,才能使其生成的树状数组 \(c[]\) 符合条件。
  • \(c[i]\) 的值实际上是所有使得 \(j+(j \ \operatorname{and} \ (-j))=i\)\(c[j]\) 的值加起来,再加上 \(a[i]\)
  • 如果 \(j+(j \ \operatorname{and} \ (-j))=i\)\(c[j]\) 全是 \(0\),但 \(c[i]\)\(0\),那么 \(a[i]\) 就必须非 \(0\)
  • 如果 \(j+(j \ \operatorname{and} \ (-j))=i\)\(c[j]\) 只有一个非 \(0\),但 \(c[i]\)\(0\),那么 \(a[i]\) 就必须非 \(0\)
  • 可以证明,其他情况下都可以让 \(a[i]\)\(0\)

代码

#include<bits/stdc++.h>
const int N=1e5+5;
int n,a[N],b[N],ans;
char sc[N];
int main(){
	int T;
	scanf("%d",&T);
	for(;T--;){
	    scanf("%d %s",&n,sc+1);
	    ans=0;
	    for(int i=1; i<=n; i++) a[i]=sc[i]-'0',b[i]=0;
	    for(int i=1; i<=n; i++){
	        if(!b[i]&&a[i]||b[i]==1&&!a[i]) ++ans;
	        if(a[i]&&(i&-i)+i<=n) ++b[(i&-i)+i];
	    }
	    printf("%d\n",ans);
    }
	return 0;
}
posted @ 2025-01-29 15:42  naroto2022  阅读(30)  评论(0)    收藏  举报