跳到主要内容

题解:CF570C Replacement

· 阅读需 2 分钟
lailai
Blogger

原题链接

题意简述

给定长度为 nn 的字符串,包含 . 和小写字母,进行 mm 次操作,每次修改一个字符,并询问将所有连续 . 转化为单个 . 所需的次数。

解题思路

设字符串中有 kk 个连续的 . 子串,长度分别为 aia_i。每个子串需要 ai1a_i - 1 次转化,总转化次数为:

i=1k(ai1)=(i=1kai)k\sum_{i=1}^k (a_i - 1) = \left( \sum_{i=1}^k a_i \right) - k

注意到,i=1kai\sum_{i=1}^k a_i 为字符串中所有 . 的总数,在每次操作中,判断是否将某个 . 替换为字母或字母替换为 .,即可更新 . 的数量。

对于每次操作分类讨论,维护 . 子串数量:

  1. . 替换为字母:如果左右两边都是字母,则 . 子串数量减少 11,转化次数加 11;如果左右两边都是 .,则 . 子串数量增加 11,转化次数减少 11
  2. 将字母替换为 .:如果左右两边都是字母,则 . 子串数量增加 11,转化次数减少 11;如果左右两边都是 .,则 . 子串数量减少 11,转化次数增加 11

参考代码

#include <bits/stdc++.h>
using namespace std;

using ll=long long;
const int N=300005;
int a[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n,m;
cin>>n>>m;
int ans=0;
for(int i=1;i<=n;i++)
{
char f;
cin>>f;
a[i]=f=='.';
if(a[i]&&a[i-1])ans++;
}
while(m--)
{
int x;
char f;
cin>>x>>f;
int y=f=='.';
if(a[x]!=y)
{
a[x]=y;
ans+=(a[x-1]+a[x+1])*(y*2-1);
}
cout<<ans<<'\n';
}
return 0;
}