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;
using namespace std;
class segment_tree {
 public:
  struct node {
    int sum, lazy;
  };
  node t[1000000];
  void build() {
    for (int i = 0; i < 1000000; i++) t[i].sum = 0, t[i].lazy = -1;
  }
  void fix(int n, int s, int e) {
    if (t[n].lazy == -1) return;
    t[n << 1].lazy = t[(n << 1) + 1].lazy = t[n].lazy;
    t[n].sum = t[n].lazy * (e - s + 1);
    t[n].lazy = -1;
  }
  void update(int n, int s, int e, int i, int j, bool v) {
    if (s == i && e == j) {
      t[n].lazy = v, fix(n, s, e);
      return;
    }
    int left = n << 1, right = left + 1, mid = (s + e) >> 1;
    fix(n, s, e);
    if (j <= mid) {
      update(left, s, mid, i, j, v);
    } else if (i > mid) {
      update(right, mid + 1, e, i, j, v);
    } else {
      update(left, s, mid, i, mid, v);
      update(right, mid + 1, e, mid + 1, j, v);
    }
    fix(left, s, mid), fix(right, mid + 1, e);
    t[n].sum = t[left].sum + t[right].sum;
  }
  long long query(int n, int s, int e, int i, int j) {
    if (s == i && e == j) {
      fix(n, s, e);
      return t[n].sum;
    }
    int left = n << 1, right = left + 1, mid = (s + e) >> 1;
    fix(n, s, e);
    if (j <= mid) return query(left, s, mid, i, j);
    if (i > mid) return query(right, mid + 1, e, i, j);
    return query(left, s, mid, i, mid) + query(right, mid + 1, e, mid + 1, j);
  }
};
int main() {
  segment_tree *a[26];
  int n, q, l, r, k, cnt[26];
  for (int i = 0; i < 26; i++) a[i] = new segment_tree(), a[i]->build();
  cin >> n >> q;
  string s;
  cin >> s;
  for (int i = 0; i < n; i++) a[s[i] - 'a']->update(1, 1, n, i + 1, i + 1, 1);
  for (int i = 0; i < q; i++) {
    memset(cnt, 0, sizeof(cnt));
    cin >> l >> r >> k;
    for (int i = 0; i < 26; i++) cnt[i] = a[i]->query(1, 1, n, l, r);
    for (int i = 0; i < 26; i++) a[i]->update(1, 1, n, l, r, 0);
    if (k == 0) {
      int le = l;
      for (int i = 25; i >= 0; i--)
        if (le + cnt[i] - 1 >= le)
          a[i]->update(1, 1, n, le, le + cnt[i] - 1, 1), le += cnt[i];
    } else {
      int le = l;
      for (int i = 0; i < 26; i++) {
        if (le + cnt[i] - 1 >= le) {
          a[i]->update(1, 1, n, le, le + cnt[i] - 1, 1);
        }
        le += cnt[i];
      }
    }
  }
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < 26; j++) {
      if (a[j]->query(1, 1, n, i + 1, i + 1) == 1) {
        s[i] = (char)('a' + j);
        break;
      }
    }
  }
  cout << s << endl;
  return 0;
}