ポストオーダーの最後に登場する頂点でインオーダーを分割する。
このコードより簡単な実装or解法がある気がする。
#include <iostream> #include <algorithm> #include <vector> #include <sstream> using namespace std; const int N = 10000 + 1; pair<int, int> node[N]; int I[N]; int P[N]; int idx[N]; int rev[N]; const int inf = 1 << 28; namespace RMQ { const int MAX_N = N; int n, dat[4 * MAX_N - 1]; void init(int _n = MAX_N) { n = 1; while (n < _n) n *= 2; for (int i = 0; i < 2 * n - 1; ++i) { dat[i] = inf; } } void update_(int k, int a) { k += n - 1; dat[k] = a; while (k > 0) { k = (k - 1) / 2; dat[k] = min(dat[k * 2 + 1], dat[k * 2 + 2]); } return ; } int query_(int a, int b, int k = 0, int l = 0, int r = RMQ::n) { if (r <= a || b <= l) return inf; if (a <= l && r <= b) return dat[k]; else { int v1 = query_(a, b, k * 2 + 1, l, (l + r) / 2); int v2 = query_(a, b, k * 2 + 2, (l + r) / 2, r); return min(v1, v2); } } void update(int k, int a) { update_(k, -1 * a); return ; } int query(int a, int b, int k = 0, int l = 0, int r = RMQ::n) { return -1 * query_(a, b, k, l, r); } }; int f(int num[], string s) { istringstream iss(s); string t; int i; for (i = 0; iss >> t; ++i) { num[i] = atoi(t.c_str()); } return i; } int rec(int begin, int end) { if (begin == end) return -1; if (begin + 1 == end) return I[begin]; int root = RMQ::query(begin, end); root = rev[P[root]]; int a = rec(begin, root); int b = rec(root + 1, end); node[I[root]] = make_pair(a, b); return I[root]; } pair<int, int> visit(int n, int sum) { if (node[n] == make_pair(-1, -1)) { return make_pair(sum, n); } pair<int, int> mn = make_pair(1 << 28, 1 << 28); if (node[n].first != -1) { mn = min(mn, visit(node[n].first, sum + node[n].first)); } if (node[n].second != -1) { mn = min(mn, visit(node[n].second, sum + node[n].second)); } return mn; } int main(void) { string in, post; while (getline(cin, in) && getline(cin, post)) { fill(node, node + N, make_pair(-1, -1)); int size; size = f(I, in); size = f(P, post); for (int i = 0; i < size; ++i) { idx[P[i]] = i; rev[I[i]] = i; } RMQ::init(); for (int i = 0; i < size; ++i) { RMQ::update(i, idx[I[i]]); } const int root = rec(0, size); cout << visit(root, root).second << endl; } return 0; }