雑記

競技プログラミングなどについての話題(?)

ABC 120 C - Unification (300)

stack の上 n ( \geq 2 ) 個をまとめて扱う問題(上2個比較して条件満たすなら 2個まとめて取り出すみたいな) で毎回めんどくさい実装をしていた気がするのでそれをサボるためのメモ

問題

0と1のみで構成された列が与えられます。
隣接した0と1を消す操作が行えるとき、最大で何回の操作ができるか出力しなさい。

本質的な解法

0と1が両方存在するときは必ずどこかで隣接している

本質的なコード

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

int main() {
  string S;
  cin >> S;

  vector<int> cnt(2);
  for (int i = 0; i < S.size(); ++i) {
    cnt[S[i] == '1']++;
  }

  cout << 2 * min(cnt[0], cnt[1]) << endl;
}

stackを用いた非本質的な解法

stack使ってシミュレーションするだけで解ける

stackを用いた非本質的なコード

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

int main() {
  string S;
  cin >> S;

  int ans = 0;


  stack<bool> st;
  for (int i = 0; i < S.size(); ++i) {
    st.push(S[i] == '1');

    while (st.size() >= 2) {
      int a = st.top();
      st.pop();
      int b = st.top();
      st.pop();

      if (a != b)
        ans += 2;
      else {
        st.push(b);
        st.push(a);
        break;
      }
    }
  }

  cout << ans << endl;
}

非本質の本質

非本質の本質のコード

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

int main() {
  string S;
  cin >> S;

  int ans = 0;

  vector<int> st;
  for (int i = 0; i < S.size(); ++i) {
    st.push_back(S[i] == '1');

    while (st.size() >= 2) {
      int sz = st.size();
      if (st[sz - 1] != st[sz - 2]) {
        ans += 2;
        st.pop_back();
        st.pop_back();
      } else {
        break;
      }
    }
  }

  cout << ans << endl;
}