#include <bits/stdc++.h>
using std::queue;
using std::vector;
using lint = long long;
using pii = std::pair<lint, lint>;
struct Dinic {
  lint inf = 123456789;
  struct edge {
    lint to, cap, rev;
    lint idx;
    edge(lint to, lint cap, lint rev, lint idx)
        : to(to), cap(cap), rev(rev), idx(idx) {}
  };
  vector<vector<edge>> G;
  vector<lint> depth, iter;
  lint s, t;
  Dinic(lint size, lint s, lint t) : s(s), t(t) {
    G.resize(size);
    depth.resize(size);
    iter.resize(size);
  }
  void add_edge(lint from, lint to, lint cap, lint idx = -1) {
    edge a = edge(to, cap, G[to].size(), idx);
    edge b = edge(from, 0, G[from].size(), idx);
    G[from].push_back(a);
    G[to].push_back(b);
  }
  void bfs() {
    std::fill(depth.begin(), depth.end(), inf);
    queue<lint> que;
    depth[s] = 0;
    que.push(s);
    while (!que.empty()) {
      lint idx = que.front();
      que.pop();
      for (auto &next : G[idx]) {
        if (depth[next.to] == inf && next.cap > 0) {
          depth[next.to] = depth[idx] + 1;
          que.push(next.to);
        }
      }
    }
  }
  lint dfs(lint idx, lint cost) {
    if (idx == t) return cost;
    for (lint &i = iter[idx]; i < G[idx].size(); i++) {
      edge &next = G[idx][i];
      if (depth[next.to] > depth[idx] && next.cap > 0) {
        lint ret = dfs(next.to, std::min(cost, next.cap));
        if (ret) {
          next.cap -= ret;
          G[next.to][next.rev].cap += ret;
          return ret;
        }
      }
    }
    return 0;
  }
  lint flow() {
    lint ret = 0;
    while (1) {
      std::fill(iter.begin(), iter.end(), 0);
      bfs();
      if (depth[t] == inf) return ret;
      lint f;
      while (f = dfs(s, inf)) ret += f;
    }
  }
};
pii limit(lint cnt, lint d) {
  d = std::min(d, cnt);
  lint a = (cnt - d + 1) / 2;
  return {a, (cnt + d) / 2};
}
bool flag = false;
lint sum = 0;
void lr_add_edge(lint u, lint v, lint ss, lint tt, pii lr, Dinic &dn) {
  lint l = lr.first, r = lr.second;
  dn.add_edge(u, v, r - l);
  dn.add_edge(u, tt, l);
  dn.add_edge(ss, v, l);
  sum += l;
  if (l > r) flag = true;
}
int main() {
  lint n, m;
  scanf("%lld %lld", &n, &m);
  lint r, b;
  scanf("%lld %lld", &r, &b);
  vector<pii> E;
  vector<lint> xx, yy;
  vector<vector<lint>> Gx, Gy;
  for (lint i = 0; i < n; i++) {
    lint a, b;
    scanf("%lld %lld", &a, &b);
    E.push_back({a, b});
    xx.push_back(a);
    yy.push_back(b);
  }
  sort(xx.begin(), xx.end());
  xx.erase(unique(xx.begin(), xx.end()), xx.end());
  sort(yy.begin(), yy.end());
  yy.erase(unique(yy.begin(), yy.end()), yy.end());
  Gx.resize(xx.size());
  Gy.resize(yy.size());
  for (lint i = 0; i < n; i++) {
    lint xidx = lower_bound(xx.begin(), xx.end(), E[i].first) - xx.begin();
    lint yidx = lower_bound(yy.begin(), yy.end(), E[i].second) - yy.begin();
    Gx[xidx].push_back(yidx);
    Gy[yidx].push_back(xidx);
  }
  vector<pii> X, Y;
  vector<pii> tmpx, tmpy;
  for (lint i = 0; i < m; i++) {
    lint t, l, d;
    scanf("%lld %lld %lld", &t, &l, &d);
    if (t == 1)
      tmpx.push_back({l, d});
    else
      tmpy.push_back({l, d});
  }
  sort(tmpx.begin(), tmpx.end());
  sort(tmpy.begin(), tmpy.end());
  for (lint i = 0; i < tmpx.size(); i++)
    if (i == 0 || tmpx[i - 1].first != tmpx[i].first) X.push_back(tmpx[i]);
  for (lint i = 0; i < tmpy.size(); i++)
    if (i == 0 || tmpy[i - 1].first != tmpy[i].first) Y.push_back(tmpy[i]);
  X.push_back({123456789000000LL, 0});
  Y.push_back({123456789000000LL, 0});
  lint ss = X.size() + Y.size() + 1, tt = X.size() + Y.size() + 2;
  lint source = 0, sink = X.size() + Y.size() + 3;
  Dinic dn(sink + 1, source, sink);
  auto L = [](lint a) { return a + 1; };
  auto R = [&](lint b) { return X.size() + b + 1; };
  lint ans = 0;
  vector<bool> color(n, 1);
  lint cntx = 0, cnty = 0;
  for (lint i = 0; i < n; i++) {
    auto xit = lower_bound(X.begin(), X.end(), std::make_pair(E[i].first, 0LL));
    auto yit =
        lower_bound(Y.begin(), Y.end(), std::make_pair(E[i].second, 0LL));
    lint a = L(xit - X.begin()), b = R(yit - Y.begin());
    if (xit == X.end() || xit->first != E[i].first) a = L(X.size() - 1), cntx++;
    if (yit == Y.end() || yit->first != E[i].second)
      b = R(Y.size() - 1), cnty++;
    if (a == L(X.size() - 1) && b == R(Y.size() - 1)) {
      ans++;
      color[i] = 0;
      continue;
    }
    dn.add_edge(a, b, 1, i);
  }
  for (lint i = 0; i < X.size() - 1; i++) {
    auto xit = lower_bound(xx.begin(), xx.end(), X[i].first);
    if (xit == xx.end() || *xit != X[i].first) continue;
    lr_add_edge(source, L(i), ss, tt,
                limit(Gx[xit - xx.begin()].size(), X[i].second), dn);
  }
  lr_add_edge(source, L(X.size() - 1), ss, tt, std::make_pair(0LL, cntx), dn);
  for (lint i = 0; i < Y.size() - 1; i++) {
    auto yit = lower_bound(yy.begin(), yy.end(), Y[i].first);
    if (yit == yy.end() || *yit != Y[i].first) continue;
    lr_add_edge(R(i), sink, ss, tt,
                limit(Gy[yit - yy.begin()].size(), Y[i].second), dn);
  }
  lr_add_edge(R(Y.size() - 1), sink, ss, tt, std::make_pair(0LL, cnty), dn);
  dn.add_edge(dn.t, dn.s, 12345678);
  dn.s = ss, dn.t = tt;
  int flow = dn.flow();
  if (flow < sum || flag) {
    printf("-1\n");
    return 0;
  }
  dn.s = source, dn.t = sink;
  ans += dn.flow();
  printf("%lld\n", ans * std::min(r, b) + (n - ans) * std::max(r, b));
  for (lint i = 0; i < X.size(); i++) {
    for (Dinic::edge e : dn.G[L(i)]) {
      if (e.idx == -1) continue;
      if (e.cap == 0) {
        color[e.idx] = 0;
      }
    }
  }
  for (lint i = 0; i < n; i++) {
    if (r < b) color[i] = !color[i];
    if (color[i])
      printf("r");
    else
      printf("b");
  }
}
