Problem: This task is very simple. Given a string S of length n and q queries each query is on the format i j k which means sort the substring consisting of the characters from i to j in non-decreasing order if k = 1 or in non-increasing order if k = 0.

Output the final string after applying the queries.

Input

The first line will contain two integers n, q (1 ≤ n ≤ 105, 0 ≤ q ≤ 50 000), the length of the string and the number of queries respectively. 

Next line contains a string S itself. It contains only lowercase English letters.

Next q lines will contain three integers each i, j, k (1 ≤ i ≤ j ≤ n, <image>).

Output

Output one line, the string S after applying the queries.

Examples

Input

10 5
abacdabcda
7 10 0
5 8 1
1 4 0
3 6 0
7 10 1


Output

cbcaaaabdd

Input

10 1
agjucbvdfk
1 10 1


Output

abcdfgjkuv

Note

First sample test explanation:

<image>

<image>

<image>

<image>

<image>

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
const int MaxA = 1e5 + 7;
struct SegmentTree {
  struct Node {
    int cnt, flag;
  } tree[26][MaxA << 2];
  Node* c;
  int id;
  void chID(int _id) {
    id = _id;
    c = tree[id];
  }
  void pushUp(int rt) {
    Node& u = c[rt];
    Node& ls = c[rt << 1];
    Node& rs = c[rt << 1 | 1];
    u.cnt = ls.cnt + rs.cnt;
  }
  void pushDown(int l, int m, int r, int rt) {
    Node& u = c[rt];
    Node& ls = c[rt << 1];
    Node& rs = c[rt << 1 | 1];
    if (~u.flag) {
      ls.flag = u.flag;
      ls.cnt = (m - l + 1) * u.flag;
      rs.flag = u.flag;
      rs.cnt = (r - m) * u.flag;
      u.flag = -1;
    }
  }
  void build(char* s, int l, int r, int rt) {
    c[rt].flag = -1;
    if (l == r) {
      c[rt].cnt = s[l] == (id + 'a');
    } else {
      int m = (l + r) >> 1;
      build(s, l, m, rt << 1);
      build(s, m + 1, r, rt << 1 | 1);
      pushUp(rt);
    }
  }
  int query(int L, int R, int l, int r, int rt) {
    if (L <= l && r <= R) {
      return c[rt].cnt;
    } else {
      int m = (l + r) >> 1;
      pushDown(l, m, r, rt);
      int res = 0;
      if (L <= m) res += query(L, R, l, m, rt << 1);
      if (m < R) res += query(L, R, m + 1, r, rt << 1 | 1);
      return res;
    }
  }
  void update(int L, int R, int x, int l, int r, int rt) {
    if (L <= l && r <= R) {
      c[rt].flag = x;
      c[rt].cnt = (r - l + 1) * x;
    } else {
      int m = (l + r) >> 1;
      pushDown(l, m, r, rt);
      if (L <= m) update(L, R, x, l, m, rt << 1);
      if (m < R) update(L, R, x, m + 1, r, rt << 1 | 1);
      pushUp(rt);
    }
  }
} st;
int n, q;
char str[MaxA];
int cnt[26];
int main() {
  while (~scanf("%d%d", &n, &q)) {
    scanf("%s", str);
    for (int i = 0; i < 26; i++) {
      st.chID(i);
      st.build(str, 0, n - 1, 1);
    }
    while (q--) {
      int L, R, op;
      scanf("%d%d%d", &L, &R, &op);
      L--;
      R--;
      if (op) {
        int cnt = 0;
        for (int i = 0; i < 26; i++) {
          st.chID(i);
          int tmp = st.query(L, R, 0, n - 1, 1);
          if (!tmp) continue;
          st.update(L, R, 0, 0, n - 1, 1);
          st.update(L + cnt, L + cnt + tmp - 1, 1, 0, n - 1, 1);
          cnt += tmp;
        }
      } else {
        int cnt = 0;
        for (int i = 25; i >= 0; i--) {
          st.chID(i);
          int tmp = st.query(L, R, 0, n - 1, 1);
          if (!tmp) continue;
          st.update(L, R, 0, 0, n - 1, 1);
          st.update(L + cnt, L + cnt + tmp - 1, 1, 0, n - 1, 1);
          cnt += tmp;
        }
      }
    }
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < 26; j++) {
        st.chID(j);
        if (st.query(i, i, 0, n - 1, 1)) {
          putchar('a' + j);
          break;
        }
      }
    }
    puts("");
  }
  return 0;
}