CF1978E 题解
特殊情况
首先考虑当 时怎么做。
一个最优的操作方案是:
先对 进行操作 ,使 拥有尽可能多的 1,再对 进行操作 ,这样 中的 1 数量就是最多的了。
一般情况
记 表示进行上述操作方案后 的区间 中的 1 的个数, 表示区间 的答案。
显然 。
而当 时(既有 或 ), 不一定等于 。
记 表示 中的第 位是否是由 变为 的, 表示 中的第 位是否是由 变为 的。
不难想到当 或 时, 都会减少一。
还有当 或 时, 也都会减少一。
所以判断这几种情况,就能算出 。
注意一些细节,具体见代码。
代码
#include<bits/stdc++.h>
using namespace std;
int T,n,q,a[200010];
bool f[200010][2];//这里的 f 即上文中的 c
char s[200010],t[200010];
int main(){
scanf("%d",&T);
while(T--){
scanf("%d",&n);
scanf("%s",s+1);
scanf("%s",t+1);
for(int i=0;i<=n+1;i++) f[i][0]=f[i][1]=0;
for(int i=2;i<n;i++){
if(s[i-1]==s[i+1]&&s[i-1]=='0'){
f[i][1]=(t[i]=='0');
t[i]='1';
}
}
for(int i=2;i<n;i++){
if(t[i-1]==t[i+1]&&t[i-1]=='1'){
f[i][0]=(s[i]=='0');
s[i]='1';
}
}
for(int i=1;i<=n;i++) a[i]=a[i-1]+(s[i]=='1');
scanf("%d",&q);
while(q--){
int l,r;
scanf("%d%d",&l,&r);
int ans=a[r]-a[l-1];
if(l==r){ //细节 1
if(f[l][0]) ans--;
printf("%d\n",ans);
continue;
}
ans-=f[l][0]+f[r][0];
if(r-l+1==2){//细节 2
printf("%d\n",ans);
continue;
}
if(l+1==r-1) ans-=(f[l+1][0]&f[l][1])|(f[r-1][0]&f[r][1]);//细节 3
else ans-=(f[l+1][0]&f[l][1])+(f[r-1][0]&f[r][1]);
printf("%d\n",ans);
}
}
return 0;
}

浙公网安备 33010602011771号