Problem p00733 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <valarray>
#include <vector>
using namespace std;

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
typedef long long ll;
const int INF = 1 << 29;
const double PI = acos(-1);
const double EPS = 1e-8;

typedef pair<int, int> pii;
pii tree[300];

int num = 0;
int parse(string s) {
  int ne = 0;
  if (s.size() == 1) {
    tree[num] = pii(-1, -1);
    return num++;
  }
  REP(i, s.size()) {
    if (s[i] == '(')
      ne++;
    else if (s[i] == ')')
      ne--;
    else if (s[i] == ' ' && ne == 1) {
      int a = parse(s.substr(1, i - 1));
      int b = parse(s.substr(i + 1, s.size() - i - 2));
      tree[num] = pii(a, b);
      return num++;
    }
  }
}

string tostr(int now, bool f) {
  if (tree[now].first == -1) {
    return "x";
  }
  string s1 = tostr(tree[now].first, f);
  string s2 = tostr(tree[now].second, f);
  if (f && s1 > s2)
    swap(s1, s2);
  return "(" + s1 + " " + s2 + ")";
}

set<string> S[300];

set<string> sub(int a) {
  set<string> res;
  if (tree[a].first != -1) {
    set<string> s1 = sub(tree[a].first), s2 = sub(tree[a].second);
    res.insert(ALL(s1));
    res.insert(ALL(s2));
  }
  res.insert(tostr(a, 1));
  return res;
}

double calc(int a) {
  if (tree[a].first == -1)
    return 0;
  int sum = 0;
  set<string> s1 = S[tree[a].first];
  set<string> s2 = S[tree[a].second];
  int uni = s2.size(), inter = 0;
  FOR(it, s1) {
    if (s2.count(*it))
      inter++;
    else
      uni++;
  }
  return (double)inter / uni;
}

int memo[300][300];
bool func(int a, int b) { // aツづ個氾アツ妥篠湘個青ォ <
                          // bツづ個氾アツ妥篠湘個青ォツ　ツづ按づァツ真
  if (memo[a][b] >= 0)
    return memo[a][b];
  double ca = calc(a), cb = calc(b);
  if (ca != cb)
    return memo[a][b] = (ca > cb);
  if (tree[a].first == -1 && tree[b].first == -1)
    return memo[a][b] = 0;
  int m1 = tree[a].first, mm1 = tree[a].second;
  int m2 = tree[b].first, mm2 = tree[b].second;
  if (func(m1, mm1))
    swap(m1, mm1);
  if (func(m2, mm2))
    swap(m2, mm2);
  // printf("%d->(%d,%d) %d->(%d,%d)\\n",
  // a,tree[a].first,tree[a].second,b,tree[b].first,tree[b].second);
  //  cout << a << " " << b << endl;
  if (func(m1, m2))
    return memo[a][b] = 1;
  if (func(m2, m1))
    return memo[a][b] = 0;
  if (func(mm1, mm2))
    return memo[a][b] = 1;
  if (func(mm2, mm1))
    return memo[a][b] = 0;
  return memo[a][b] = 0;
}

void myswap(int a) {
  if (tree[a].first == -1)
    return;
  myswap(tree[a].first);
  myswap(tree[a].second);
  swap(tree[a].first, tree[a].second);
}

void solve(int now, bool f) {
  if (tree[now].first == -1)
    return;
  solve(tree[now].first, 0);
  solve(tree[now].second, 1);
  // cout << now << " " << f << endl;
  // cout << tostr(now,0) << endl;
  // cout << calc(tree[now].first) << " " <<  calc(tree[now].second) << " " <<
  // func(tree[now].first, tree[now].second) << endl;
  if (f ^ func(tree[now].first, tree[now].second)) {
    myswap(now);
    // swap(tree[now].first, tree[now].second);
  }
  // cout << tostr(now,0) << endl;
  // cout << tostr(now,1) << endl;
}

int main() {
  string line;
  while (getline(cin, line), line != "0") {
    num = 0;
    parse(line);
    REP(i, num) { S[i] = sub(i); }
    memset(memo, -1, sizeof(memo));
    solve(num - 1, 0);
    cout << tostr(num - 1, 0) << endl;
    ;
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <valarray>
#include <vector>
using namespace std;

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
typedef long long ll;
const int INF = 1 << 29;
const double PI = acos(-1);
const double EPS = 1e-8;

typedef pair<int, int> pii;
pii tree[300];

int num = 0;
int parse(string s) {
  int ne = 0;
  if (s.size() == 1) {
    tree[num] = pii(-1, -1);
    return num++;
  }
  REP(i, s.size()) {
    if (s[i] == '(')
      ne++;
    else if (s[i] == ')')
      ne--;
    else if (s[i] == ' ' && ne == 1) {
      int a = parse(s.substr(1, i - 1));
      int b = parse(s.substr(i + 1, s.size() - i - 2));
      tree[num] = pii(a, b);
      return num++;
    }
  }
}

string tostr(int now, bool f) {
  if (tree[now].first == -1) {
    return "x";
  }
  string s1 = tostr(tree[now].first, f);
  string s2 = tostr(tree[now].second, f);
  if (f && s1 > s2)
    swap(s1, s2);
  return "(" + s1 + " " + s2 + ")";
}

set<string> S[300];

set<string> sub(int a) {
  set<string> res;
  if (tree[a].first != -1) {
    set<string> s1 = sub(tree[a].first), s2 = sub(tree[a].second);
    res.insert(ALL(s1));
    res.insert(ALL(s2));
  }
  res.insert(tostr(a, 1));
  return res;
}

double calc(int a) {
  if (tree[a].first == -1)
    return 0;
  int sum = 0;
  set<string> s1 = S[tree[a].first];
  set<string> s2 = S[tree[a].second];
  int uni = s2.size(), inter = 0;
  FOR(it, s1) {
    if (s2.count(*it))
      inter++;
    else
      uni++;
  }
  return (double)inter / uni;
}

bool func(int a, int b) { // aツづ個氾アツ妥篠湘個青ォ <
                          // bツづ個氾アツ妥篠湘個青ォツ　ツづ按づァツ真
  double ca = calc(a), cb = calc(b);
  if (ca != cb)
    return ca > cb;
  if (tree[a].first == -1 && tree[b].first == -1)
    return 0;
  int m1 = tree[a].first, mm1 = tree[a].second;
  int m2 = tree[b].first, mm2 = tree[b].second;
  if (func(m1, mm1))
    swap(m1, mm1);
  if (func(m2, mm2))
    swap(m2, mm2);

  if (func(m1, m2))
    return 1;
  if (func(m2, m1))
    return 0;
  if (func(mm1, mm2))
    return 1;
  if (func(mm2, mm1))
    return 0;
  return 0;
}

void myswap(int a) {
  if (tree[a].first == -1)
    return;
  myswap(tree[a].first);
  myswap(tree[a].second);
  swap(tree[a].first, tree[a].second);
}

void solve(int now, bool f) {
  if (tree[now].first == -1)
    return;
  solve(tree[now].first, 0);
  solve(tree[now].second, 1);
  // cout << now << " " << f << endl;
  // cout << tostr(now,0) << endl;
  // cout << calc(tree[now].first) << " " <<  calc(tree[now].second) << " " <<
  // func(tree[now].first, tree[now].second) << endl;
  if (f ^ func(tree[now].first, tree[now].second)) {
    myswap(now);
    // swap(tree[now].first, tree[now].second);
  }
  // cout << tostr(now,0) << endl;
  // cout << tostr(now,1) << endl;
}

int main() {
  string line;
  while (getline(cin, line), line != "0") {
    num = 0;
    parse(line);
    REP(i, num) { S[i] = sub(i); }
    solve(num - 1, 0);
    cout << tostr(num - 1, 0) << endl;
    ;
  }
}