#include <bits/stdc++.h>
using namespace std;
constexpr int kN = int(1E5 + 10);
constexpr int kInf = 0x3f3f3f3f;
template <typename T>
T ABS(T n) {
  return n >= 0 ? n : -n;
}
static inline char Get_Raw_Char() {
  static char buf[1 << 16], *p = buf, *end = buf;
  if (p == end) {
    if ((end = buf + fread(buf, 1, 1 << 16, stdin)) == buf) return '\0';
    p = buf;
  }
  return *p++;
}
static inline int Get_Digit() {
  char c = Get_Raw_Char();
  while (!isdigit(c)) c = Get_Raw_Char();
  return int(c - '0');
}
static inline int Get_PInt() {
  char c = Get_Raw_Char();
  int ret;
  while (!isdigit(c)) c = Get_Raw_Char();
  ret = int(c - '0');
  while (isdigit(c = Get_Raw_Char())) ret = ret * 10 + int(c - '0');
  return ret;
}
static inline int Get_Int() {
  char c = Get_Raw_Char();
  bool neg = false;
  int ret;
  while (!isdigit(c)) {
    if (c == '-') neg = true;
    c = Get_Raw_Char();
  }
  ret = int(c - '0');
  while (isdigit(c = Get_Raw_Char())) ret = ret * 10 + int(c - '0');
  if (neg) return -ret;
  return ret;
}
static inline long long int Get_ll() {
  char c = Get_Raw_Char();
  bool neg = false;
  long long int ret;
  while (!isdigit(c)) {
    if (c == '-') neg = true;
    c = Get_Raw_Char();
  }
  ret = int(c - '0');
  while (isdigit(c = Get_Raw_Char())) ret = ret * 10 + int(c - '0');
  if (neg) return -ret;
  return ret;
}
static inline long long int Get_Pll() {
  char c = Get_Raw_Char();
  long long int ret;
  while (!isdigit(c)) c = Get_Raw_Char();
  ret = int(c - '0');
  while (isdigit(c = Get_Raw_Char())) ret = ret * 10 + int(c - '0');
  return ret;
}
template <typename T>
static inline void Read_P(T &n) {
  static_assert(is_integral<T>::value);
  char c = Get_Raw_Char();
  while (!isdigit(c)) c = Get_Raw_Char();
  n = int(c - '0');
  while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
  return;
}
template <typename T>
static inline void Read(T &n) {
  static_assert(is_integral<T>::value);
  char c = Get_Raw_Char();
  bool neg = false;
  while (!isdigit(c)) {
    if (c == '-') neg = true;
    c = Get_Raw_Char();
  }
  n = int(c - '0');
  while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
  if (neg) n = -n;
  return;
}
template <typename T>
static inline void Read_Digit(T &n) {
  static_assert(is_integral<T>::value);
  char c = Get_Raw_Char();
  while (!isdigit(c)) c = Get_Raw_Char();
  n = int(c - '0');
  return;
}
template <typename T, typename... Targs>
static inline void Read(T &n, Targs &...Fargs) {
  Read(n);
  return Read(Fargs...);
}
template <typename T, typename... Targs>
static inline void Read_Digit(T &n, Targs &...Fargs) {
  Read_Digit(n);
  return Read_Digit(Fargs...);
}
template <typename T, typename... Targs>
static inline void Read_P(T &n, Targs &...Fargs) {
  Read_P(n);
  return Read_P(Fargs...);
}
template <typename T = int>
struct Dinic {
  struct Edge {
    int to, rev;
    T cap;
    Edge(int a, int b, T c) { to = a, rev = b, cap = c; }
  };
  vector<Edge> *graph;
  int *dep, *iter, *went;
  int size;
  void init(int n) {
    size = n;
    delete graph;
    graph = new vector<Edge>[size];
    delete went;
    went = new int[size];
    delete iter;
    iter = new int[size];
    delete dep;
    dep = new int[size];
    return;
  }
  void AddEdge(int u, int v, T c) {
    graph[u].push_back(Edge(v, int(graph[v].size()), c));
    graph[v].push_back(Edge(u, int(graph[u].size()) - 1, 0));
    return;
  }
  void AddEdge_B(int u, int v, T c) {
    graph[u].push_back(Edge(v, int(graph[v].size()), c));
    graph[v].push_back(Edge(u, int(graph[u].size()) - 1, c));
    return;
  }
  void Reweight() {
    for (int i = 0; i < size; i++)
      for (Edge &j : graph[i])
        if (j.to > i)
          j.cap = graph[j.to][j.rev].cap =
              (j.cap + graph[j.to][j.rev].cap) >> 1;
    return;
  }
  void Bfs(int s, int t) {
    queue<int> q;
    went[s] = t;
    iter[s] = dep[s] = 0;
    q.push(s);
    while (!q.empty()) {
      int now = q.front();
      q.pop();
      for (Edge i : graph[now])
        if (i.cap > 0 && went[i.to] != t) {
          went[i.to] = t;
          dep[i.to] = dep[now] + 1;
          iter[i.to] = 0;
          q.push(i.to);
        }
    }
    return;
  }
  T Dfs(int u, int t, T nv) {
    if (u == t) return nv;
    for (int &i = iter[u]; i < int(graph[u].size()); i++) {
      Edge &nxt = graph[u][i];
      if (nxt.cap > 0 && dep[nxt.to] > dep[u]) {
        T tmp = Dfs(nxt.to, t, min(nxt.cap, nv));
        if (tmp > 0) {
          nxt.cap -= tmp;
          graph[nxt.to][nxt.rev].cap += tmp;
          return tmp;
        }
      }
    }
    return 0;
  }
  T solve(int s, int t) {
    int cnt = went[s];
    T ans = 0, kInf = numeric_limits<T>::max();
    while (true) {
      Bfs(s, ++cnt);
      if (went[s] != went[t]) break;
      T f = 0;
      while ((f = Dfs(s, t, kInf)) > 0) ans += f;
    }
    return ans;
  }
  T operator()(int s, int t) { return solve(s, t); }
  vector<int> S_side(int s) {
    vector<int> ans;
    for (int i = 0; i < size; i++)
      if (went[s] == went[i]) ans.push_back(i);
    return ans;
  }
};
Dinic<int> dinic;
bitset<kN> color;
int x[kN], y[kN], type[kN], l[kN], d[kN], x_cnt[kN << 1], y_cnt[kN << 1],
    diff[kN << 2], x_restriction[kN << 1], y_restriction[kN << 1];
map<int, int> ma[kN << 1];
int main() {
  int n, m, r, b;
  scanf("%d%d%d%d", &n, &m, &r, &b);
  for (int i = 1; i <= n; i++) scanf("%d%d", &x[i], &y[i]);
  for (int i = 1; i <= m; i++) scanf("%d%d%d", &type[i], &l[i], &d[i]);
  vector<int> X, Y;
  for (int i = 1; i <= n; i++) X.push_back(x[i]);
  for (int i = 1; i <= m; i++)
    if (type[i] == 1) X.push_back(l[i]);
  sort(X.begin(), X.end());
  X.resize(unique(X.begin(), X.end()) - X.begin());
  for (int i = 1; i <= n; i++)
    x[i] = lower_bound(X.begin(), X.end(), x[i]) - X.begin() + 1;
  for (int i = 1; i <= m; i++)
    if (type[i] == 1)
      l[i] = lower_bound(X.begin(), X.end(), l[i]) - X.begin() + 1;
  for (int i = 1; i <= n; i++) Y.push_back(y[i]);
  for (int i = 1; i <= m; i++)
    if (type[i] == 2) Y.push_back(l[i]);
  sort(Y.begin(), Y.end());
  Y.resize(unique(Y.begin(), Y.end()) - Y.begin());
  for (int i = 1; i <= n; i++)
    y[i] = lower_bound(Y.begin(), Y.end(), y[i]) - Y.begin() + 1;
  for (int i = 1; i <= m; i++)
    if (type[i] == 2)
      l[i] = lower_bound(Y.begin(), Y.end(), l[i]) - Y.begin() + 1;
  for (int i = 1; i <= n; i++) x_cnt[x[i]]++;
  for (int i = 1; i <= n; i++) y_cnt[y[i]]++;
  int xsz = int(X.size()), ysz = int(Y.size());
  int s = xsz + ysz + 1, t = xsz + ysz + 2;
  int second = xsz + ysz + 3, T = xsz + ysz + 4;
  int total_ST = 0;
  dinic.init(xsz + ysz + 4 + 1);
  dinic.AddEdge(t, s, kInf);
  for (int i = 1; i <= xsz; i++) x_restriction[i] = x_cnt[i];
  for (int i = 1; i <= ysz; i++) y_restriction[i] = y_cnt[i];
  for (int i = 1; i <= m; i++)
    if (type[i] == 1)
      x_restriction[l[i]] = min(x_restriction[l[i]], d[i]);
    else
      y_restriction[l[i]] = min(y_restriction[l[i]], d[i]);
  for (int i = 1; i <= xsz; i++) {
    int lower = (x_cnt[i] - x_restriction[i] + 1) / 2, upper = x_cnt[i] - lower;
    if (upper < lower) goto NO;
    diff[s] -= lower;
    diff[i] += lower;
    dinic.AddEdge(s, i, upper - lower);
  }
  for (int i = 1; i <= ysz; i++) {
    int lower = (y_cnt[i] - y_restriction[i] + 1) / 2, upper = y_cnt[i] - lower;
    if (upper < lower) goto NO;
    diff[i + xsz] -= lower;
    diff[t] += lower;
    dinic.AddEdge(i + xsz, t, upper - lower);
  }
  for (int i = 1; i <= n; i++) {
    dinic.AddEdge(x[i], y[i] + xsz, 1);
  }
  for (int i = 1; i <= t; i++) {
    if (diff[i] > 0) {
      dinic.AddEdge(second, i, diff[i]);
      total_ST += diff[i];
    } else if (diff[i] < 0)
      dinic.AddEdge(i, T, -diff[i]);
  }
  if (dinic(second, T) == total_ST) {
    long long int cnt = dinic(s, t);
    long long int ans =
        r > b ? cnt * b + (n - cnt) * r : cnt * r + (n - cnt) * b;
    printf("%lld\n", ans);
    for (int i = 1; i <= xsz; i++)
      for (Dinic<int>::Edge j : dinic.graph[i])
        if (s > j.to && j.to >= xsz)
          ma[i][j.to - xsz] += dinic.graph[j.to][j.rev].cap;
    for (int i = 1; i <= n; i++)
      if (ma[x[i]][y[i]]) {
        ma[x[i]][y[i]]--;
        color[i] = true;
      }
    if (r > b)
      for (int i = 1; i <= n; i++) color[i] = !color[i];
    for (int i = 1; i <= n; i++) printf("%c", color[i] ? 'r' : 'b');
  } else
    goto NO;
  return 0;
NO:
  printf("-1\n");
}
