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 N = 1e5 + 10;
struct Node {
  int a[26];
  void clear() { memset(a, 0, sizeof(a)); }
  Node operator+(const Node& A) const {
    Node x;
    for (int i = 0; i < 26; i++) x.a[i] = a[i] + A.a[i];
    return x;
  }
};
struct Tree {
  int l, r, tag;
  Node v;
} T[N << 2];
char s[N];
void Build(int rt, int l, int r) {
  T[rt].l = l;
  T[rt].r = r;
  T[rt].tag = -1;
  if (l == r) {
    T[rt].v.a[s[l] - 'a'] = 1;
    return;
  }
  int mid = l + r >> 1;
  Build(rt << 1, l, mid);
  Build(rt << 1 | 1, mid + 1, r);
  T[rt].v = T[rt << 1].v + T[rt << 1 | 1].v;
}
void down(int rt) {
  T[rt << 1].tag = T[rt].tag;
  T[rt << 1 | 1].tag = T[rt].tag;
  T[rt << 1].v.clear();
  T[rt << 1 | 1].v.clear();
  T[rt << 1].v.a[T[rt].tag] = T[rt << 1].r - T[rt << 1].l + 1;
  T[rt << 1 | 1].v.a[T[rt].tag] = T[rt << 1 | 1].r - T[rt << 1 | 1].l + 1;
  T[rt].tag = -1;
}
void update(int rt, int l, int r, int nu) {
  if (l <= T[rt].l && T[rt].r <= r) {
    T[rt].tag = nu;
    T[rt].v.clear();
    T[rt].v.a[nu] = T[rt].r - T[rt].l + 1;
    return;
  }
  if (~T[rt].tag) down(rt);
  int mid = T[rt].l + T[rt].r >> 1;
  if (l <= mid) update(rt << 1, l, r, nu);
  if (r > mid) update(rt << 1 | 1, l, r, nu);
  T[rt].v = T[rt << 1].v + T[rt << 1 | 1].v;
}
Node query(int rt, int l, int r) {
  if (l <= T[rt].l && T[rt].r <= r) return T[rt].v;
  if (~T[rt].tag) down(rt);
  Node res;
  res.clear();
  int mid = T[rt].l + T[rt].r >> 1;
  if (l <= mid) res = res + query(rt << 1, l, r);
  if (r > mid) res = res + query(rt << 1 | 1, l, r);
  return res;
}
void print(int rt) {
  if (T[rt].l == T[rt].r) {
    for (int i = 0; i < 26; i++)
      if (T[rt].v.a[i]) {
        putchar('a' + i);
        return;
      }
  }
  if (~T[rt].tag) down(rt);
  print(rt << 1);
  print(rt << 1 | 1);
}
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  scanf("%s", s + 1);
  Build(1, 1, n);
  while (m--) {
    int l, r, op;
    scanf("%d%d%d", &l, &r, &op);
    if (op) {
      Node v = query(1, l, r);
      int u = l;
      for (int i = 0; i < 26; i++) {
        if (v.a[i]) {
          update(1, u, u + v.a[i] - 1, i);
          u += v.a[i];
        }
      }
    } else {
      Node v = query(1, l, r);
      int u = l;
      for (int i = 25; i >= 0; i--) {
        if (v.a[i]) {
          update(1, u, u + v.a[i] - 1, i);
          u += v.a[i];
        }
      }
    }
  }
  print(1);
  return 0;
}