#include <bits/stdc++.h>   using namespace std;   namespace {   using namespace std;   template <typename flow_t = long long>   struct PushRelabel {     struct Edge {       int to, rev;       flow_t f, c;     };     vector<vector<Edge>> g;     vector<flow_t> ec;     vector<Edge*> cur;     vector<vector<int>> hs;     vector<int> H;     PushRelabel(int n) : g(n), ec(n), cur(n), hs(2 * n), H(n) {}     void add_edge(int s, int t, flow_t cap, flow_t rcap = 0) {       if (s == t) return;       Edge a = {t, (int)g[t].size(), 0, cap};       Edge b = {s, (int)g[s].size(), 0, rcap};       g[s].push_back(a);       g[t].push_back(b);     }     void add_flow(Edge& e, flow_t f) {       Edge& back = g[e.to][e.rev];       if (!ec[e.to] && f) hs[H[e.to]].push_back(e.to);       e.f += f;       e.c -= f;       ec[e.to] += f;       back.f -= f;       back.c += f;       ec[back.to] -= f;     }     flow_t max_flow(int s, int t) {       const int n = g.size();       ec.assign(n, 0);       cur.assign(n, nullptr);       hs.assign(2 * n, {});       H.assign(n, 0);       int v = g.size();       H[s] = v;       ec[t] = 1;       vector<int> co(2 * v);       co[0] = v - 1;       for (int i = 0; i < v; ++i) cur[i] = g[i].data();       for (auto& e : g[s]) add_flow(e, e.c);       if (hs[0].size())         for (int hi = 0; hi >= 0;) {           int u = hs[hi].back();           hs[hi].pop_back();           while (ec[u] > 0)             if (cur[u] == g[u].data() + g[u].size()) {               H[u] = 1e9;               for (auto& e : g[u])                 if (e.c && H[u] > H[e.to] + 1) H[u] = H[e.to] + 1, cur[u] = &e;               if (++co[H[u]], !--co[hi] && hi < v)                 for (int i = 0; i < v; ++i)                   if (hi < H[i] && H[i] < v) {                     --co[H[i]];                     H[i] = v + 1;                   }               hi = H[u];             } else if (cur[u]->c && H[u] == H[cur[u]->to] + 1)               add_flow(*cur[u], min(ec[u], cur[u]->c));             else               ++cur[u];           while (hi >= 0 && hs[hi].empty()) --hi;         }       return -ec[s];     }   };   template <typename flow_t = long long>   struct MaxFlow {     static constexpr flow_t INF = numeric_limits<flow_t>::max();     PushRelabel<flow_t> flow;     MaxFlow(const int n) : flow(n) {}     inline void add_arc(const int u, const int v, const flow_t capacity) {       flow.add_edge(u, v, capacity);     }     inline void add_edge(const int u, const int v, const flow_t capacity) {       flow.add_edge(u, v, capacity, capacity);     }     inline void add_infinite_arc(const int u, const int v) {       flow.add_edge(u, v, INF);     }     inline void add_infinite_edge(const int u, const int v) {       flow.add_edge(u, v, INF, INF);     }     flow_t solve(const int s, const int t) { return flow.max_flow(s, t); }   };   template <typename flow_t>   class MaxFlowLR {    private:     static constexpr flow_t INF = numeric_limits<flow_t>::max();     int n;     vector<flow_t> from_source, to_sink, outgoing_capacity;     vector<tuple<int, int, flow_t>> demands;     flow_t total_demand;     bool invalid;     PushRelabel<flow_t> flow;       public:     MaxFlowLR(const int n)         : n(n),           from_source(n),           to_sink(n),           outgoing_capacity(n),           total_demand(0),           invalid(false),           flow(n + 2) {}     void add_arc(const int u, const int v, const flow_t demand,                  const flow_t capacity) {       if (demand > capacity) {         invalid = true;         return;       }       if (u != v) {         from_source[v] += demand;         to_sink[u] += demand;         flow.add_edge(u, v, capacity - demand);         demands.push_back({u, v, demand});         total_demand += demand;         outgoing_capacity[u] += capacity;       }     }     flow_t solve(const int s, const int t) {       if (invalid) {         return -1;       }       const int source = n;       const int sink = n + 1;       for (int v = 0; v < n; ++v) {         if (from_source[v] != 0) {           flow.add_edge(source, v, from_source[v]);         }         if (to_sink[v] != 0) {           flow.add_edge(v, sink, to_sink[v]);         }       }       flow.add_edge(t, s, INF);       const flow_t flow_aux = flow.max_flow(source, sink);       if (s != t) {         flow.g[s].pop_back();         flow.g[t].pop_back();       }       for (int v = n - 1; v >= 0; --v) {         if (to_sink[v] != 0) {           flow.g[sink].pop_back();           flow.g[v].pop_back();         }         if (from_source[v] != 0) {           flow.g[source].pop_back();           flow.g[v].pop_back();         }       }       if (flow_aux != total_demand) return -1;       const flow_t flow_new = flow.max_flow(s, t);       flow_t total_flow = outgoing_capacity[s];       for (const auto& e : flow.g[s]) total_flow -= e.c;       return total_flow;     }     vector<map<int, flow_t>> retrieve() {       vector<map<int, flow_t>> ans(n);       for (int u = 0; u < n; ++u)         for (const auto& e : flow.g[u])           if (e.f > 0) ans[u][e.to] += e.f, ans[e.to][u] -= e.f;       for (auto t : demands)         if (get<2>(t) > 0)           ans[get<0>(t)][get<1>(t)] += get<2>(t),               ans[get<1>(t)][get<0>(t)] -= get<2>(t);       return ans;     }   };   }  // namespace   inline int divceil(const int x, const int y) {     const int q = x / y;     return q * y == x ? q : q + 1;   }   inline long long divceil(const long long x, const long long y) {     const long long q = x / y;     return q * y == x ? q : q + 1;   }   map<int, int> coordinate_compression(vector<int> v) {     sort(v.begin(), v.end());     const int n = unique(v.begin(), v.end()) - v.begin();     map<int, int> compr;     for (int i = 0; i < n; ++i) compr[v[i]] = i;     return compr;   }   map<long long, int> coordinate_compression(vector<long long> v) {     sort(v.begin(), v.end());     const int n = unique(v.begin(), v.end()) - v.begin();     map<long long, int> compr;     for (int i = 0; i < n; ++i) compr[v[i]] = i;     return compr;   }   int main() {     int n, m;     scanf( %d%d , &n, &m);     int r, b;     scanf( %d%d , &r, &b);     bool flip = false;     if (r >= b) {       flip = true;       swap(r, b);     }     vector<std::pair<int, int>> original_points;     vector<int> allx, ally;     for (int i = 0; i < n; ++i) {       int x, y;       scanf( %d%d , &x, &y);       original_points.emplace_back(x, y);       allx.push_back(x);       ally.push_back(y);     }     map<int, int> comprx = coordinate_compression(allx),                   compry = coordinate_compression(ally);     const int xlines = comprx.rbegin()->second + 1;     const int ylines = compry.rbegin()->second + 1;     vector<int> xdeg(xlines), ydeg(ylines);     vector<int> xcons(xlines), ycons(ylines);     vector<std::pair<int, int>> points;     for (const std::pair<int, int> p : original_points) {       const int xx = comprx[p.first];       const int yy = compry[p.second];       points.emplace_back(xx, yy);       ++xdeg[xx];       ++ydeg[yy];       ++xcons[xx];       ++ycons[yy];     }     while (m--) {       int t, l, d;       scanf( %d%d%d , &t, &l, &d);       if (t == 1) {         const auto it = comprx.find(l);         if (it != comprx.end()) xcons[it->second] = min(xcons[it->second], d);       } else {         const auto it = compry.find(l);         if (it != compry.end()) ycons[it->second] = min(ycons[it->second], d);       }     }     MaxFlowLR<long long> dinic(2 + xlines + ylines);     const int source = 0;     const int sink = 1;     const auto get_xvert = [&](const int i) { return 2 + i; };     const auto get_yvert = [&](const int i) { return 2 + xlines + i; };     for (int i = 0; i < xlines; ++i) {       const int L = divceil(xdeg[i] - xcons[i], 2);       const int R = (xdeg[i] + xcons[i]) / 2;       dinic.add_arc(source, get_xvert(i), L, R);     }     for (int i = 0; i < ylines; ++i) {       const int L = divceil(ydeg[i] - ycons[i], 2);       const int R = (ydeg[i] + ycons[i]) / 2;       dinic.add_arc(get_yvert(i), sink, L, R);     }     for (const std::pair<int, int> p : points)       dinic.add_arc(get_xvert(p.first), get_yvert(p.second), 0, 1);     long long flow_value = dinic.solve(source, sink);     if (flow_value == -1) {       puts( -1 );       return 0;     }     long long ans = flow_value * r + (n - flow_value) * b;     cout << ans << endl;     map<std::pair<int, int>, int> red;     auto flow = dinic.retrieve();     for (int i = 0; i < xlines; ++i) {       const int x = get_xvert(i);       for (const auto p : flow[x]) {         const int j = p.first - 2 - xlines;         const int f = p.second;         if (j >= 0) red[std::pair<int, int>(i, j)] += f;       }     }     for (const std::pair<int, int> p : points) {       int& v = red[p];       if (v) {         v--;         putchar(flip ?  b  :  r );       } else {         putchar(flip ?  r  :  b );       }     }     cout << endl;   }