Codeforces
CF Step
Youtube Linkedin Discord Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Code: Ghostfires

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

struct State {
    int c[3];
    unsigned char s0, s1, s2;

    bool operator==(const State &other) const {
        return c[0] == other.c[0] && c[1] == other.c[1] && c[2] == other.c[2] &&
               s0 == other.s0 && s1 == other.s1 && s2 == other.s2;
    }
};

struct StateHash {
    static uint64_t splitmix64(uint64_t x) {
        x += 0x9e3779b97f4a7c15ULL;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL;
        x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL;
        return x ^ (x >> 31);
    }

    size_t operator()(const State &st) const {
        uint64_t h = 0;
        h ^= splitmix64((uint64_t)st.c[0] + 1000003ULL);
        h ^= splitmix64((uint64_t)st.c[1] + 2000003ULL);
        h ^= splitmix64((uint64_t)st.c[2] + 3000003ULL);
        h ^= splitmix64((uint64_t)st.s0 + 4000003ULL);
        h ^= splitmix64((uint64_t)st.s1 + 5000003ULL);
        h ^= splitmix64((uint64_t)st.s2 + 6000003ULL);
        return (size_t)h;
    }
};

static inline int upper_bound_len(int a, int b, int c) {
    int x = a, y = b, z = c;
    if (x < y)
        swap(x, y);
    if (y < z)
        swap(y, z);
    if (x < y)
        swap(x, y);
    return min(x + y + z, 2 * (y + z) + 1);
}

static inline State make_state(const array<int, 3> &cnt, const string &ans) {
    State st;
    st.c[0] = cnt[0];
    st.c[1] = cnt[1];
    st.c[2] = cnt[2];
    st.s0 = st.s1 = st.s2 = 3; // empty

    int n = (int)ans.size();
    auto id = [&](char ch) -> unsigned char {
        if (ch == 'R')
            return 0;
        if (ch == 'G')
            return 1;
        return 2;
    };

    if (n >= 1)
        st.s2 = id(ans[n - 1]);
    if (n >= 2)
        st.s1 = id(ans[n - 2]);
    if (n >= 3)
        st.s0 = id(ans[n - 3]);
    return st;
}

static string solve_dominant_case(array<int, 3> cnt) {
    vector<pair<int, char>> v = {{cnt[0], 'R'}, {cnt[1], 'G'}, {cnt[2], 'B'}};
    sort(v.begin(), v.end(), greater<>());

    char mx = v[0].second;
    int mxCnt = v[0].first;
    int otherCnt = v[1].first + v[2].first;

    string others;
    others.reserve(otherCnt);
    others.append(v[1].first, v[1].second);
    others.append(v[2].first, v[2].second);

    string ans;
    ans.reserve(2 * otherCnt + 1);

    for (char ch : others) {
        ans.push_back(mx);
        ans.push_back(ch);
    }
    if (mxCnt > otherCnt)
        ans.push_back(mx);

    return ans;
}

static string solve_two_colors(array<int, 3> cnt) {
    vector<pair<int, char>> v;
    if (cnt[0] > 0)
        v.push_back({cnt[0], 'R'});
    if (cnt[1] > 0)
        v.push_back({cnt[1], 'G'});
    if (cnt[2] > 0)
        v.push_back({cnt[2], 'B'});

    if (v.size() == 1)
        return string(1, v[0].second);

    sort(v.begin(), v.end(), greater<>());
    int a = v[0].first, b = v[1].first;
    char A = v[0].second, B = v[1].second;

    int useB = min(a, b);
    int useA = min(a, b + 1);

    string ans;
    ans.reserve(useA + useB);

    for (int i = 0; i < useB; ++i) {
        ans.push_back(A);
        ans.push_back(B);
    }
    if (useA > useB)
        ans.push_back(A);

    return ans;
}

static string solve_balanced_dfs(array<int, 3> cnt) {
    const char CH[3] = {'R', 'G', 'B'};
    int total = cnt[0] + cnt[1] + cnt[2];

    string ans;
    ans.reserve(total);

    vector<unsigned char> tried(total + 1, 0);
    unordered_set<State, StateHash> dead;
    dead.reserve((size_t)total * 2 + 10);

    auto can_put = [&](int color) -> bool {
        int n = (int)ans.size();
        char ch = CH[color];
        if (cnt[color] == 0)
            return false;
        if (n >= 1 && ans[n - 1] == ch)
            return false;
        if (n >= 3 && ans[n - 3] == ch)
            return false;
        return true;
    };

    int pos = 0;
    while (true) {
        if (pos == total)
            break;

        vector<int> cand;
        for (int c = 0; c < 3; ++c) {
            if (tried[pos] & (1u << c))
                continue;
            if (!can_put(c))
                continue;

            cnt[c]--;
            int ub = upper_bound_len(cnt[0], cnt[1], cnt[2]);
            int rem = cnt[0] + cnt[1] + cnt[2];
            if (ub < rem) {
                cnt[c]++;
                continue;
            }

            ans.push_back(CH[c]);
            State nxt = make_state(cnt, ans);
            ans.pop_back();

            if (dead.find(nxt) != dead.end()) {
                cnt[c]++;
                continue;
            }

            cnt[c]++;
            cand.push_back(c);
        }

        if (!cand.empty()) {
            sort(cand.begin(), cand.end(), [&](int x, int y) {
                if (cnt[x] != cnt[y])
                    return cnt[x] > cnt[y];
                return x < y;
            });

            int c = cand[0];
            tried[pos] |= (1u << c);
            ans.push_back(CH[c]);
            cnt[c]--;
            ++pos;
            tried[pos] = 0;
        } else {
            State cur = make_state(cnt, ans);
            dead.insert(cur);

            if (pos == 0)
                break;

            --pos;
            int last = (ans.back() == 'R' ? 0 : ans.back() == 'G' ? 1 : 2);
            ans.pop_back();
            cnt[last]++;
        }
    }

    return ans;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T;
    cin >> T;
    while (T--) {
        array<int, 3> cnt{};
        cin >> cnt[0] >> cnt[1] >> cnt[2];

        int total = cnt[0] + cnt[1] + cnt[2];

        int x = cnt[0], y = cnt[1], z = cnt[2];
        if (x < y)
            swap(x, y);
        if (y < z)
            swap(y, z);
        if (x < y)
            swap(x, y);

        int bestLen = min(total, 2 * (y + z) + 1);

        int nonzero = (cnt[0] > 0) + (cnt[1] > 0) + (cnt[2] > 0);

        string ans;
        if (nonzero == 1) {
            if (cnt[0] > 0)
                ans = "R";
            else if (cnt[1] > 0)
                ans = "G";
            else
                ans = "B";
        } else if (nonzero == 2) {
            ans = solve_two_colors(cnt);
        } else {
            if (bestLen < total) {
                ans = solve_dominant_case(cnt);
            } else {
                ans = solve_balanced_dfs(cnt);
            }
        }

        if ((int)ans.size() > bestLen)
            ans.resize(bestLen);
        cout << ans << '\n';
    }

    return 0;
}