#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const double eps = 1e-6;
template <typename A, typename B>
ostream& operator<<(ostream& os, const pair<A, B>& p) {
  return os << p.first << ',' << p.second;
}
template <typename T>
struct point {
  T x, y;
  point(T xx = 0, T yy = 0) : x(xx), y(yy) {}
  T len2() const { return x * x + y * y; }
  double len() const { return sqrt(double(len2())); }
  bool operator==(const point<T>& p) const { return x == p.x && y == p.y; }
};
template <typename T>
point<T> operator+(const point<T>& a, const point<T>& b) {
  return point<T>(a.x + b.x, a.y + b.y);
}
template <typename T>
point<T> operator-(const point<T>& a, const point<T>& b) {
  return point<T>(a.x - b.x, a.y - b.y);
}
template <typename T>
T scal(const point<T>& a, const point<T>& b) {
  return a.x * b.x + a.y * b.y;
}
template <typename T>
T vect(const point<T>& a, const point<T>& b) {
  return a.x * b.y - a.y * b.x;
}
template <typename T>
ostream& operator<<(ostream& os, const point<T>& p) {
  return os << '(' << p.x << ',' << p.y << ')';
}
const int maxn = 100100;
pair<int, pair<int, int> > a[maxn], b[maxn];
int below[maxn], direct[maxn], belowsecond[maxn];
long long d[maxn][2];
int main() {
  int n;
  cin >> n;
  for (int i = 0; i < n; i++) {
    scanf("%d%d", &a[i].second.first, &a[i].first);
    a[i].second.second = i;
  }
  int m;
  cin >> m;
  for (int i = 0; i < m; i++) {
    scanf("%d%d", &b[i].second.first, &b[i].first);
    b[i].second.second = i;
  }
  sort(a, a + n);
  sort(b, b + m);
  memset(direct, -1, sizeof(direct));
  memset(below, -1, sizeof(below));
  memset(belowsecond, -1, sizeof(belowsecond));
  for (int i = 0; i < n; i++) {
    pair<int, pair<int, int> >* d1 =
        lower_bound(b, b + m,
                    pair<int, pair<int, int> >(
                        a[i].first, pair<int, int>(a[i].second.first, 0)));
    pair<int, pair<int, int> >* d2 =
        lower_bound(b, b + m,
                    pair<int, pair<int, int> >(
                        a[i].first - 1, pair<int, int>(a[i].second.first, 0)));
    if (d1 != b + m && d1->first == a[i].first &&
        d1->second.first >= a[i].second.first) {
      direct[i] = d1->second.second;
    }
    if (d2 != b + m && d2->first + 1 == a[i].first &&
        d2->second.first >= a[i].second.first) {
      below[i] = d2->second.second;
      d2++;
      if (d2 != b + m && d2->first + 1 == a[i].first &&
          d2->second.first >= a[i].second.first) {
        belowsecond[i] = d2->second.second;
      }
    }
  }
  long long mx = 0;
  for (int i = 0; i < n; i++) {
    if (direct[i] >= 0) {
      long long q = max(d[i][0], d[i][1]);
      d[i + 1][1] = max(d[i + 1][1], a[i].second.first + q);
    }
    if (below[i] >= 0) {
      d[i + 1][0] = max(d[i + 1][0], d[i][0] + a[i].second.first);
      if (i > 0 && direct[i - 1] != below[i]) {
        d[i + 1][0] = max(d[i + 1][0], d[i][1] + a[i].second.first);
      }
      if (i > 0 && direct[i - 1] == below[i] && belowsecond[i] >= 0) {
        d[i + 1][0] = max(d[i + 1][0], d[i][1] + a[i].second.first);
      }
    }
    d[i + 1][0] = max(d[i + 1][0], max(d[i][0], d[i][1]));
    mx = max(mx, max(d[i + 1][0], d[i + 1][1]));
  }
  cout << mx << endl;
  int cur = n;
  int t = 0;
  if (d[cur][t] != mx) t++;
  assert(d[cur][t] == mx);
  vector<pair<int, int> > res;
  set<int> guyused;
  for (; cur > 0; cur--) {
    if (res.size()) {
      guyused.insert(res.back().second);
    }
    if (d[cur - 1][0] == d[cur][t]) {
      t = 0;
      continue;
    }
    if (d[cur - 1][1] == d[cur][t]) {
      t = 1;
      continue;
    }
    int p = a[cur - 1].second.first;
    if (!guyused.count(direct[cur - 1])) {
      if (p + d[cur - 1][1] == mx && direct[cur - 1] >= 0) {
        res.push_back(
            pair<int, int>(a[cur - 1].second.second, direct[cur - 1]));
        mx -= p;
        t = 1;
        continue;
      }
      if (p + d[cur - 1][0] == mx && direct[cur - 1] >= 0) {
        res.push_back(
            pair<int, int>(a[cur - 1].second.second, direct[cur - 1]));
        mx -= p;
        t = 0;
        continue;
      }
    }
    assert(below[cur - 1] >= 0);
    if (!guyused.count(below[cur - 1])) {
      if (d[cur - 1][0] + p == mx) {
        res.push_back(pair<int, int>(a[cur - 1].second.second, below[cur - 1]));
        mx -= p;
        t = 0;
        continue;
      }
      if (cur - 2 < 0 ||
          (direct[cur - 2] != below[cur - 1] && d[cur - 1][1] + p == mx)) {
        res.push_back(pair<int, int>(a[cur - 1].second.second, below[cur - 1]));
        mx -= p;
        t = 1;
        continue;
      }
    }
    assert(!guyused.count(belowsecond[cur - 1]));
    if (cur - 2 >= 0 && direct[cur - 2] == below[cur - 1] &&
        belowsecond[cur - 1] >= 0 && d[cur - 1][1] + p == mx) {
      res.push_back(
          pair<int, int>(a[cur - 1].second.second, belowsecond[cur - 1]));
      mx -= p;
      t = 1;
      continue;
    }
    assert(0);
  }
  printf("%d\n", res.size());
  for (int i = 0; i < res.size(); i++) {
    printf("%d %d\n", res[i].second + 1, res[i].first + 1);
  }
  return 0;
}
