abc418d
AtCoder ABC418 D XNOR Operation
题意
给定一个长度为 \(n\) 的 01 串 \(s\),每次可以选择相邻的两个位置。如果两个位置字符相同,把它们缩成 \(1\),否则缩成 \(0\)。求 \(s\) 中有多少个子串经过操作可以变成 \(1\)。\(1\leq n\leq 2\times 10^5\)。
题解
动态规划。令 \(f_{i,0/1}\) 表示以 \(i\) 结尾且最终变为 \(0/1\) 的子串个数。当 \(s_i=1\) 时,显然 \(f_{i,0}=f_{i-1,0},f_{i,1}=f_{i-1,1}+1\)。当 \(s_i=0\) 则有 \(f_{i,0}=f_{i-1,1}+1,f_{i,1}=f_{i-1,0}\)。而最终答案就是 \(\sum f_{i,1}\)。复杂度 \(O(n)\)。aclink。
代码
#include<bits/stdc++.h>
#define i64 long long
#define L(a,b,c,d) for(int a=b;a<=c;a+=d)
#define R(a,b,c,d) for(int a=b;a>=c;a-=d)
using namespace std;
const int N=2e5+5;
void solve();
int n,f[N][2];
i64 ans;
char s[N];
signed main(){
int Test=1;
// scanf("%d",&Test);
while(Test--) solve();
return 0;
}
void solve(){
scanf("%d%s",&n,s+1);
L(i,1,n,1){
if(s[i]=='1'){
f[i][1]=f[i-1][1]+1;
f[i][0]=f[i-1][0];
}
else{
f[i][1]=f[i-1][0];
f[i][0]=f[i-1][1]+1;
}
ans+=f[i][1];
}
printf("%lld\n",ans);
}
本文来自博客园,作者:jess1ca1o0g3,转载请注明原文链接:https://www.cnblogs.com/jess1ca1o0g3/p/19103353

浙公网安备 33010602011771号