cf1873G

原题链接:https://codeforces.com/contest/1873/problem/G
题目背景:

       我们拥有一个只包含AB的字符串,我们可以进行两种操作(每次操作都可获得一枚硬币):

                1.将AB转换为BC。

                2.将BA转换成CB。

思路:

        执行每次操作都会消除掉一个A(获得一枚硬币)获得一个C,通过观察可以发现我们在消除AAAAB和BAAAA时都可以将A全部消除既变成BCCCC和CCCCB。

        如何使用以上规律呢?由于字符串初始时只包含AB所以字符串可以分为以下几种:

                1.BAAABAAABAAAB(B完全包含A)

                2.BAAABAAABAAA(以B开头)

                3.AAABAAABAAAB(以B结尾)

                4.AAAABBAAAA(中间有两个及以上的B)

                5.AAABAAABAAA(B的数量比A段的数量少一个)

        上面的1.2.3.4.都可以完全消除,所以我们只用考虑情况5,由于B比A段多一个,所以我们直接丢弃掉最少的一组即可,可证明以上贪心策略成立。
                

数据范围:

        t <= 1000,s 总和小于2e5

时间复杂度:

        O(n)

ac代码: 
#include 

#define ioscc ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'
using namespace std;

typedef unsigned long long ull;
typedef long long ll;
typedef pair pii;

const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, 1, 0, -1};
const int MAX = (1ll << 31) - 1;
const int MIN = 1 << 31;
const int N = 1e5 + 10;

void solve()
{
    string s;
    cin >> s;
    int n = s.size();
    bool flag = (s[0] == 'B' || s[n - 1] == 'B');

    for (int i = 1; i < n - 1; i++)
    {
        if (s[i] == s[i - 1] && s[i] == 'B')
        {
            flag = 1;
            break;
        }
    }

    int cnt = 0;
    vector v;
    for (int i = 0; i < n; i++)
    {
        if (s[i] == 'A')
        {
            cnt++;
        }
        else
        {
            v.push_back(cnt);
            cnt = 0;
        }
    }

    if (cnt)
        v.push_back(cnt);

    if (!v.size())
    {
        cout << 0 << endl;
        return;
    }

    sort(v.begin(), v.end());

    ll ans = 0;

    if (flag)
        ans += v[0];

    for (int i = 1; i < v.size(); i++)
    {
        ans += v[i];
    }

    cout << ans << endl;
}

int main()
{
    int T;
    cin >> T;
    while (T--)
        solve();

    return 0;
}

你可能感兴趣的:(codeforces,算法,c++)