SRM443 Mediumを解いてみた

id:chokudaiせんせのオーダーを極める思考法 (1/3) - ITmedia エンタープライズを読んだのでSRM443 Mediumに再挑戦。
そのSRMのときは頭悪いことにダイクストラ法使って制限時間オーバーで落とされたけど。。*1
しかし記事に載ってる方法で普通に解いても面白くないので、幅優先をベースにした力技で解いてみた。オーダーもへったくれもねえなw
…こんなの実戦じゃ書けないです><

#include <map>
using namespace std;
class BinaryFlips{
  int hoge[200001];
  int queue[200001];
  bool visited[200001];
  map<int, int> even, odd;
public:
  int skip(int n) {
    map<int,int>::iterator i =
      (n%2 == 0) ? even.upper_bound(n)
                 : odd.upper_bound(n) ;
    -- i;
    if (i->first <= n && n <= i->second) {
      return i->second;
    }
    return n;
  }
  void add(int begin, int last) {
    if (skip(begin) != skip(last)) {
      if (begin%2 == 0) even[begin] = skip(last);
      else odd[begin] = skip(last);
    }
  }
  int minimalMoves(int A, int B, int K) {
    even[-1] = -1;
    odd[-1] = -1;
    int N = A+B;
    memset(visited, 0, sizeof(visited));
    int n = 0;
    queue[n++] = A;
    visited[A] = true;
    hoge[A] = 0;
    for (int p = 0; p < n; ++ p) {
      int a = queue[p];
      if (a % K == 0) return hoge[a] + a / K;
      int begin = max(a-K, K-a);
      int last = min(a+K, 2*N-a-K);
      for (int i = begin; i <= last; i += 2) {
        if (i % K == 0) return hoge[a] + 1 + i / K;
        if (visited[i]) {
          i = skip(i);
        } else {
          visited[i] = true;
          queue[n++] = i;
          hoge[i] = hoge[a] + 1;
        }
      }
      add(begin, last);
    }
    return -1;
  }
};

*1:そのときの回答 たぶん要ログイン