1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【AtCoder 反省会】AtCoder Beginner Contest 421

Posted at

今回の成績

AB 正答
(全体的に難しかった)

A問題

自分の回答

int main()
{
    int N;
    cin >> N;
    vec<str> S(N);
    FOR(i, N)
    cin >> S[i];

    int X;
    str Y;
    cin >> X >> Y;

    cout << ((S[X - 1] == Y) ? "Yes" : "No") << endl;

    return 0;
}

振り返り

前回の反省を活かして、少し丁寧に見直した。
無事一発正解。

B問題

自分の回答

static ull calc_next(ull lhs, ull rhs)
{
    ull x = lhs + rhs;
    str x_as_str = to_string(x);
    reverse(all(x_as_str));
    ull rev_x = stoull(x_as_str);
    return rev_x;
}

// index : 1-based
static ull calc(ull a1, ull a2, int index)
{
    if (index == 1)
        return a1;
    if (index == 2)
        return a2;

    FOR(i, index - 2)
    {
        ull next = calc_next(a1, a2);
        a1 = a2;
        a2 = next;
    }

    return a2;
}

int main()
{
    ull X, Y;
    cin >> X >> Y;

    ull lhs = X;
    ull rhs = Y;

    ull ans = calc(lhs, rhs, 10);
    cout << ans << endl;
}

振り返り

やることをメソッドに分割して、整理しながら作れた印象。
無事一発正解。

C問題

途中までの回答

ull impl(const str &s, int length)
{
    vec<char> c(all(s));

    ull cnt = 0;
    while (true)
    {
        bool should_do = false;
        FOR(i, length)
        {
            if (c[i] == c[i + 1])
            {
                should_do = true;
                break;
            }
        }
        if (!should_do)
            break;

        std::set<int> sep_left_indexes;

        FOR(i, length - 1)
        {
            if (i == 0)
                continue;

            if (c[i - 1] == c[i] && c[i] != c[i + 1])
            {
                if (sep_left_indexes.find(i + 1) == sep_left_indexes.end() && sep_left_indexes.find(i - 1) == sep_left_indexes.end())
                    sep_left_indexes.insert(i);
            }
        }

        cnt += sep_left_indexes.size();
        for (int i : sep_left_indexes)
        {
            char tmp = c[i];
            c[i] = c[i + 1];
            c[i + 1] = tmp;
        }

        cout << "===\n";
        for (int i : sep_left_indexes)
            cout << i << " ";
        cout << "\n";
        for (char ch : c)
            cout << ch;
        cout << "\n";
        cout << "===\n";
    }

    return cnt;
}

int main()
{
    int N;
    cin >> N;
    str S;
    cin >> S; // 2N

    cout << impl(S, N << 1) << endl;
}

振り返り

どういうアルゴリズムでやればいいのか、分からなかった。
解説にあった「2パターン試し、最小の方を取る」考えはあったが、そこからが詰まってしまった。
残り60分くらいになったので、解くのは諦め、DEFG問題に移る。(これはいい判断だと思う)

DEFG問題をザッと見てみる

難しいの多くね??と困惑。
クエリ系のアルゴリズムが比較的得意なので、F問題に狙いをつけ、残り時間を使って取り組む。
コンテスト後の解説を見ても、F問題以外は言っていることがよく分からなかった。

F問題

自分の回答 1回目

案の定、実行時間超過。

int main()
{
    vec<int> A;
    A.reserve(1e5);
    A.push_back(0);

    int Q;
    cin >> Q;
    FOR(j, Q)
    {
        int type;
        cin >> type;
        if (type == 1)
        {
            int x;
            cin >> x;

            for (int i = 0; i < A.size(); ++i)
            {
                if (A[i] == x)
                {
                    A.insert(A.begin() + i + 1, j + 1);
                    break;
                }
            }
        }
        else
        {
            int x, y;
            cin >> x >> y;

            auto it_x = find(all(A), x);
            auto it_y = find(all(A), y);
            if (it_x > it_y)
                swap(it_x, it_y);

            int sum = reduce(it_x + 1, it_y);
            A.erase(it_x + 1, it_y);

            cout << sum << endl;
        }

        // cout << "A: ";
        // for (auto a : A)
        //     cout << a << " ";
        // cout << endl;
    }
}

自分の回答 2回目

find系の処理を軽量化しようと、インデックス配列的なものにしてみた。
結果、全く高速化されなかった。残念…。
時間が経つのは早く、この提出でコンテスト時間終了。

int main()
{
    int Q;
    cin >> Q;

    // jがAのインデックスの何番目にあるかを記録するメモ
    // int index = indices[i] : 数字iがAのindex番目にある
    // -1なら無い
    vec<int> indices(Q, -1);
    indices[0] = 0;

    for (int j = 1; j <= Q; ++j)
    {
        int type;
        cin >> type;
        if (type == 1)
        {
            int x;
            cin >> x;

            int idx = indices[x] + 1;
            for (int k = 0; k < j; ++k)
            {
                if (indices[k] >= idx)
                    ++indices[k];
            }
            indices[j] = idx;
        }
        else
        {
            int x, y;
            cin >> x >> y;

            int x_index = indices[x];
            int y_index = indices[y];
            if (x_index > y_index)
                swap(x_index, y_index);

            int sum = 0;
            for (int k = 1; k < j; ++k)
            {
                int idx = indices[k];
                if (x_index < idx && idx < y_index)
                {
                    sum += k;
                    indices[k] = -1;
                }
            }

            cout << sum << endl;
        }

        // vec<int> A;
        // A.reserve(j);
        // for (int idx = 0; idx <= j; ++idx)
        // {
        //     for (int k = 0; k < indices.size(); ++k)
        //     {
        //         if (indices[k] == idx)
        //         {
        //             A.push_back(k);
        //             continue;
        //         }
        //     }
        // }
        // cout << "A: ";
        // for (int a : A)
        //     cout << a << " ";
        // cout << endl;
        // cout << "I: ";
        // for (int i = 0; i <= j; ++i)
        //     cout << indices[i] << " ";
        // cout << endl;
    }
}

振り返り

解説にあった連結リストの方法を使いたかった。
自分に解ける難易度ではあったが、けっこう頭を使って書かなければいけないので、そんなにたくさん試行できないのが辛いところ。
DEFG問題に関しては、「方針を立ててやってみる」サイクルを3回くらいしか出来ないものと思ったほうが良いか。

総括

難しい問題が多かったので、とりあえず最初の2問を完答出来たのはヨシ!
C問題に見切りを付けたのも、いい判断だと思う。(F問題の方が簡単だった)
思ったより時間は短く、そんなに試行できない ので、一回一回の方針立て・提出を丁寧にしたい。

次回も頑張ろう!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?