1 #include <cstdio>
2 #include <iostream>
3 #include <cstring>
4 #include <algorithm>
5 using namespace std;
6 struct edge{int l,r,v;}tree[400010];
7 char s[100010];
8 int n,m,f[30];
9 void build(int l,int r,int d)
10 {
11 tree[d].l=l,tree[d].r=r;
12 if (l==r)
13 {
14 tree[d].v=s[l]-'a'+1;
15 return;
16 }
17 int mid=(l+r)/2;
18 build(l,mid,d*2),build(mid+1,r,d*2+1);
19 if (tree[d*2].v==tree[d*2+1].v) tree[d].v=tree[d*2].v;
20 }
21 void getnum(int l,int r,int d)
22 {
23 if (tree[d].l>=l&&tree[d].r<=r&&tree[d].v!=0)
24 {
25 f[tree[d].v]+=tree[d].r-tree[d].l+1;
26 return;
27 }
28 if (tree[d].v) tree[d*2].v=tree[d].v,tree[d*2+1].v=tree[d].v;
29 int mid=(tree[d].l+tree[d].r)/2;
30 if (mid>=l) getnum(l,r,d*2);
31 if (mid<r) getnum(l,r,d*2+1);
32 }
33 void change(int l,int r,int d,int x)
34 {
35 if (tree[d].l>=l&&tree[d].r<=r||tree[d].v==x)
36 {
37 tree[d].v=x;
38 return;
39 }
40 if (tree[d].v) tree[d*2].v=tree[d].v,tree[d*2+1].v=tree[d].v,tree[d].v=0;
41 int mid=(tree[d].l+tree[d].r)/2;
42 if (l<=mid) change(l,r,d*2,x);
43 if (mid<r) change(l,r,d*2+1,x);
44 if (tree[d*2].v==tree[d*2+1].v) tree[d].v=tree[d*2].v;
45 }
46 void out(int d)
47 {
48 if (tree[d].v)
49 {
50 for (int i=1;i<=tree[d].r-tree[d].l+1;i++) printf("%c",tree[d].v+'a'-1);
51 return;
52 }
53 out(d*2),out(d*2+1);
54 }
55 int main()
56 {
57 freopen("string.in","r",stdin);
58 freopen("string.out","w",stdout);
59 scanf("%d%d",&n,&m);
60 scanf("%s",s+1);
61 build(1,n,1);
62 for (int j=1;j<=m;j++)
63 {
64 int l,r,x;
65 scanf("%d%d%d",&l,&r,&x);
66 memset(f,0,sizeof(f));
67 getnum(l,r,1);
68 if (x==1)
69 for (int i=1;i<=26;i++)
70 {
71 if (f[i]) change(l,l+f[i]-1,1,i),l=l+f[i];
72 }
73 else
74 for (int i=26;i>=1;i--)
75 {
76 if (f[i]) change(l,l+f[i]-1,1,i),l=l+f[i];
77 }
78 }
79 out(1);
80 return 0;
81 }