#include <bits/stdc++.h>
using namespace std;
namespace Dango {
const int MAXN = 200005, INF = 0x3f3f3f3f;
namespace Dinic {
struct Edge {
  int from, to, cap, flow;
};
vector<Edge> edges;
vector<int> g[MAXN << 1];
int s, t;
int d[MAXN << 1], dur[MAXN << 1];
void add(int u, int v, int cap) {
  edges.push_back((Edge){u, v, cap, 0});
  edges.push_back((Edge){v, u, 0, 0});
  int s = edges.size();
  g[u].push_back(s - 2);
  g[v].push_back(s - 1);
}
bool bfs() {
  queue<int> q;
  static bool vis[MAXN];
  memset(vis, 0, sizeof(vis));
  d[s] = 1;
  vis[s] = true;
  q.push(s);
  while (!q.empty()) {
    int x = q.front();
    q.pop();
    for (int i = 0; i < g[x].size(); i++) {
      Edge &e = edges[g[x][i]];
      if (!vis[e.to] && e.cap > e.flow) {
        vis[e.to] = true;
        d[e.to] = d[x] + 1;
        q.push(e.to);
      }
    }
  }
  return vis[t];
}
int dfs(int x, int a) {
  if (x == t || !a) return a;
  int flow = 0, f;
  for (int &i = dur[x]; i < g[x].size(); i++) {
    Edge &e = edges[g[x][i]];
    if (d[e.to] == d[x] + 1 && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0) {
      e.flow += f;
      edges[g[x][i] ^ 1].flow -= f;
      flow += f;
      a -= f;
      if (!a) break;
    }
  }
  return flow;
}
int work(int u, int v) {
  int res = 0;
  s = u;
  t = v;
  while (bfs()) {
    memset(dur, 0, sizeof(dur));
    res += dfs(s, INF);
  }
  return res;
}
}  // namespace Dinic
struct shell {
  int x, y;
} p[MAXN];
int n, m, r, b;
int x[MAXN], y[MAXN];
int sx[MAXN], sy[MAXN];
int dx[MAXN], dy[MAXN];
int val[MAXN << 1];
int S, T;
long long tot, res, ans;
bool tag;
int read() {
  int x = 0, f = 0;
  char ch = getchar();
  while (!isdigit(ch)) {
    f |= (ch == '-');
    ch = getchar();
  }
  while (isdigit(ch)) {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  return f ? -x : x;
}
void init() {
  for (int i = 1; i <= n; i++) {
    x[i] = p[i].x;
    y[i] = p[i].y;
  }
  sort(x + 1, x + n + 1);
  sort(y + 1, y + n + 1);
  x[0] = unique(x + 1, x + n + 1) - x - 1;
  y[0] = unique(y + 1, y + n + 1) - y - 1;
  for (int i = 1; i <= n; i++) {
    p[i].x = lower_bound(x + 1, x + x[0] + 1, p[i].x) - x;
    p[i].y = lower_bound(y + 1, y + y[0] + 1, p[i].y) - y;
    sx[p[i].x]++;
    sy[p[i].y]++;
    Dinic::add(p[i].x + 1, p[i].y + x[0] + 1, 1);
  }
}
int work() {
  n = read();
  m = read();
  r = read();
  b = read();
  if (r > b) {
    swap(r, b);
    tag = true;
  }
  for (int i = 1; i <= n; i++) {
    p[i].x = read();
    p[i].y = read();
  }
  init();
  for (int i = 1; i <= x[0]; i++) dx[i] = sx[i];
  for (int i = 1; i <= y[0]; i++) dy[i] = sy[i];
  for (int i = 1; i <= m; i++) {
    int t = read(), l = read(), d = read();
    if (t == 1) {
      int pos = lower_bound(x + 1, x + x[0] + 1, l) - x;
      if (x[pos] != l) continue;
      dx[pos] = min(dx[pos], d);
    }
    if (t == 2) {
      int pos = lower_bound(y + 1, y + y[0] + 1, l) - y;
      if (y[pos] != l) continue;
      dy[pos] = min(dy[pos], d);
    }
  }
  for (int i = 1; i <= x[0]; i++) {
    int up = (sx[i] + dx[i]) / 2, down = sx[i] - up;
    if (up < down) {
      printf("-1");
      return 0;
    }
    Dinic::add(1, i + 1, up - down);
    val[1] -= down;
    val[i + 1] += down;
  }
  for (int i = 1; i <= y[0]; i++) {
    int up = (sy[i] + dy[i]) / 2, down = sy[i] - up;
    if (up < down) {
      printf("-1");
      return 0;
    }
    Dinic::add(i + x[0] + 1, x[0] + y[0] + 2, up - down);
    val[i + x[0] + 1] -= down;
    val[x[0] + y[0] + 2] += down;
  }
  Dinic::add(x[0] + y[0] + 2, 1, INF);
  T = x[0] + y[0] + 3;
  for (int i = 1; i < T; i++) {
    if (val[i] > 0) {
      Dinic::add(S, i, val[i]);
      tot += val[i];
    }
    if (val[i] < 0) Dinic::add(i, T, -val[i]);
  }
  tot -= Dinic::work(S, T);
  if (tot) {
    printf("-1");
    return 0;
  }
  res = Dinic::work(1, T - 1);
  ans = res * r + (n - res) * b;
  printf("%lld\n", ans);
  for (int i = 0; i < n; i++)
    (Dinic::edges[i * 2].flow ^ tag) ? printf("r") : printf("b");
  return 0;
}
}  // namespace Dango
int main() { return Dango::work(); }
