#include <bits/stdc++.h>
using namespace std;
const int Maxn = 100005;
int n, m, r, b, row_lim[Maxn], col_lim[Maxn];
;
vector<int> row, col, Row[Maxn], Col[Maxn];
struct node {
  int x, y;
} w[Maxn];
struct limit {
  int type, l, d;
} q[Maxn];
namespace dinic {
const int MAXN = 3 * Maxn, MAXM = 10 * Maxn;
int h[MAXN], cur[MAXN], dis[MAXN], d[MAXN], S, T, cnt;
struct node {
  int to, next;
  int v;
  int pair;
} e[2 * MAXM];
void AddEdge(int x, int y, int v, int pair) {
  e[cnt] = (node){y, h[x], v, pair};
  h[x] = cnt;
}
void AddEdge(int x, int y, int v) {
  AddEdge(x, y, v, ++cnt + 1);
  AddEdge(y, x, 0, ++cnt - 1);
}
bool bfs() {
  memset(dis, 0x3f, sizeof(dis));
  dis[S] = 0;
  queue<int> Q;
  Q.push(S);
  while (Q.size()) {
    int x = Q.front();
    Q.pop();
    for (int p = h[x]; p; p = e[p].next) {
      int y = e[p].to;
      if (e[p].v && dis[y] > dis[x] + 1) {
        dis[y] = dis[x] + 1;
        Q.push(y);
      }
    }
  }
  return dis[T] != 0x3f3f3f3f;
}
int dfs(int x, int Maxflow) {
  if (!Maxflow || x == T) return Maxflow;
  int flow = 0;
  for (int& p = cur[x]; p; p = e[p].next) {
    int y = e[p].to, ret;
    if (dis[y] != dis[x] + 1) continue;
    ret = dfs(y, min(Maxflow, e[p].v));
    e[p].v -= ret;
    e[e[p].pair].v += ret;
    flow += ret;
    Maxflow -= ret;
    if (!Maxflow) break;
  }
  if (!flow) dis[x] = 0;
  return flow;
}
int dinic(int s, int t) {
  S = s, T = t;
  int ans = 0;
  while (bfs()) {
    memcpy(cur, h, sizeof(h));
    ans += dfs(S, INT_MAX);
  }
  return ans;
}
int solve(int s, int t, vector<int> v,
          vector<tuple<int, int, int, int>>& edge) {
  int S = 0, T, sum = 0;
  for (int i : v) S = max(i, S);
  T = (++S) + 1;
  for (auto& e : edge) {
    int src, dst, min, max;
    tie(src, dst, min, max) = e;
    if (min > max) return -1;
    d[src] -= min;
    d[dst] += min;
    AddEdge(src, dst, max - min);
  }
  for (int i : v)
    if (d[i] > 0)
      AddEdge(S, i, d[i]), sum += d[i];
    else if (d[i] < 0)
      AddEdge(i, T, -d[i]);
  AddEdge(t, s, INT_MAX);
  int flow = dinic(S, T);
  if (flow != sum) return -1;
  return dinic(s, t);
}
void print(int n, int l, int r, bool rev) {
  for (int i = 1; i <= n; i++) {
    bool succ = false;
    for (int p = h[i]; p && !succ; p = e[p].next) {
      int y = e[p].to;
      if (l <= y && y <= r && !e[p].v) succ = true, cout << (rev ? 'b' : 'r');
    }
    if (!succ) cout << (rev ? 'r' : 'b');
  }
  cout << "\n";
}
}  // namespace dinic
int main() {
  bool rev = false;
  scanf("%d%d%d%d", &n, &m, &r, &b);
  if (r > b) swap(r, b), rev = true;
  for (int i = 1; i <= n; i++) scanf("%d%d", &w[i].x, &w[i].y);
  for (int i = 1; i <= m; i++) scanf("%d%d%d", &q[i].type, &q[i].l, &q[i].d);
  for (int i = 1; i <= n; i++) row.push_back(w[i].x), col.push_back(w[i].y);
  sort(row.begin(), row.end());
  sort(col.begin(), col.end());
  row.erase(unique(row.begin(), row.end()), row.end());
  col.erase(unique(col.begin(), col.end()), col.end());
  for (int i = 1; i <= n; i++)
    w[i].x = lower_bound(row.begin(), row.end(), w[i].x) - row.begin() + 1;
  for (int i = 1; i <= n; i++)
    w[i].y = lower_bound(col.begin(), col.end(), w[i].y) - col.begin() + 1;
  for (int i = 1; i <= n; i++) Row[w[i].x].push_back(i);
  for (int i = 1; i <= n; i++) Col[w[i].y].push_back(i);
  for (size_t i = 1; i <= row.size(); i++) row_lim[i] = n;
  for (size_t i = 1; i <= col.size(); i++) col_lim[i] = n;
  for (int i = 1; i <= m; i++) {
    auto& vec = q[i].type == 1 ? row : col;
    int* lim = q[i].type == 1 ? row_lim : col_lim;
    if (!binary_search(vec.begin(), vec.end(), q[i].l)) continue;
    q[i].l = lower_bound(vec.begin(), vec.end(), q[i].l) - vec.begin() + 1;
    lim[q[i].l] = min(lim[q[i].l], q[i].d);
  }
  int S = row.size() + col.size() + n + 1, T = S + 1, id = n;
  vector<int> v;
  vector<tuple<int, int, int, int>> edge;
  for (size_t i = 1; i <= row.size(); i++) {
    edge.emplace_back(S, ++id,
                      max(0, (int(Row[i].size()) - row_lim[i] + 1) / 2),
                      (int(Row[i].size()) + row_lim[i]) / 2);
    for (auto j : Row[i]) edge.emplace_back(id, j, 0, 1);
  }
  for (size_t i = 1; i <= col.size(); i++) {
    edge.emplace_back(++id, T,
                      max(0, (int(Col[i].size()) - col_lim[i] + 1) / 2),
                      (int(Col[i].size()) + col_lim[i]) / 2);
    for (auto j : Col[i]) edge.emplace_back(j, id, 0, 1);
  }
  for (int i = 1; i <= T; i++) v.push_back(i);
  int ans = dinic::solve(S, T, v, edge);
  if (ans == -1)
    puts("-1");
  else {
    cout << 1ll * ans * r + 1ll * (n - ans) * b << "\n";
    dinic::print(n, n + row.size() + 1, S - 1, rev);
  }
  return 0;
}
