// generated at caterpillow.github.io/byot
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
// custom monoid
const ll mod = 1e9 + 7;
const ll m = 27;
ll mpow(ll x, ll y) {
ll res = 1;
while (y) {
if (y & 1) res = (res * x) % mod;
x = (x * x) % mod;
y >>= 1;
}
return res;
}
// You can implement your own monoid here for custom operations.
struct Value {
ll hash, rhash, size;
Value operator+(const Value& oth) const {
Value res {};
res.hash = ((hash * mpow(27, oth.size)) % mod + oth.hash) % mod;
res.rhash = (rhash + (oth.rhash * mpow(27, size)) % mod) % mod;
res.size = size + oth.size;
return res;
}
};
const Value vid = {0, 0, 0};
// end custom code
mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
using ptr = struct Node*;
struct Node {
Value val;
Value agg;
int sz;
int pri;
ptr l, r;
Node() {
pri = mt();
val = vid;
agg = vid;
sz = 1;
l = r = nullptr;
}
Node(Value val) : val(val), agg(val) {
pri = mt();
sz = 1;
l = r = nullptr;
}
~Node() {
delete l;
delete r;
}
};
int sz(ptr n) { return n ? n->sz : 0; };
Value agg(ptr n) { return n ? n->agg : vid; }
ptr pull(ptr n) {
if (!n) return nullptr;
n->sz = sz(n->l) + 1 + sz(n->r);
n->agg = agg(n->l) + n->val + agg(n->r);
return n;
}
ptr merge(ptr l, ptr r) {
if (!l || !r) return l ? l : r;
if (l->pri > r->pri) return l->r = merge(l->r, r), pull(l);
else return r->l = merge(l, r->l), pull(r);
}
// [-inf, i) and [i, inf]
pair<ptr, ptr> spliti(ptr n, int i) {
if (!n) return {nullptr, nullptr};
if (i <= sz(n->l)) {
auto [l, r] = spliti(n->l, i);
n->l = r;
return {l, pull(n)};
} else {
auto [l, r] = spliti(n->r, i - 1 - sz(n->l));
n->r = l;
return {pull(n), r};
}
}
// cuts out [lo, hi)
tuple<ptr, ptr, ptr> spliti(ptr n, int lo, int hi) {
auto [lm, r] = spliti(n, hi);
auto [l, m] = spliti(lm, lo);
return {l, m, r};
}
// inserts node such that it will be at index i. only insert single nodes
void insi(ptr& n, ptr it, int i) {
if (!n) { n = it; return; }
if (n->pri < it->pri) {
auto [l, r] = spliti(n, i);
it->l = l, it->r = r, n = it;
} else if (i <= sz(n->l)) insi(n->l, it, i);
else insi(n->r, it, i - 1 - sz(n->l));
pull(n);
}
Value queryi(ptr n, int lo, int hi) {
if (!n || lo >= sz(n) || hi <= 0) return vid;
if (lo <= 0 && sz(n) <= hi) return n->agg;
return queryi(n->l, lo, hi) + (lo <= sz(n->l) && sz(n->l) < hi ? n->val : vid) + queryi(n->r, lo - 1 - sz(n->l), hi - 1 - sz(n->l));
}
void heapify(ptr n) {
if (!n) return;
ptr mx = n;
if (n->l && n->l->pri > mx->pri) mx = n->l;
if (n->r && n->r->pri > mx->pri) mx = n->r;
if (mx != n) swap(n->pri, mx->pri), heapify(mx);
}
ptr build(vector<ptr>& ns, int l = 0, int r = -69) {
if (r == -69) r = (int) ns.size() - 1;
if (l > r) return nullptr;
if (l == r) return ns[l];
int m = (l + r) / 2;
ns[m]->l = build(ns, l, m - 1);
ns[m]->r = build(ns, m + 1, r);
heapify(ns[m]);
return pull(ns[m]);
}
template <typename Op>
void tour(ptr n, Op op) {
stack<ptr> stk;
while (n || !stk.empty()) {
for (; n; n = n->l) stk.push(n);
n = stk.top(); stk.pop();
op(n);
n = n->r;
}
}
/*
- include merge
- include 3-way split by index (and size, and split by index)
- include point insert by index
- include build (and heapify)
- include tour
- include range queries (and range aggregates)
*/
main() {
cin.tie(0)->sync_with_stdio(0);
int n, q; cin >> n >> q;
string st; cin >> st;
vector<ptr> ns(n);
for (int i = 0; i < n; i++) {
ns[i] = new Node({st[i] - 'a' + 1, st[i] - 'a' + 1, 1});
}
ptr treap = build(ns);
while (q--) {
int t; cin >> t;
if (t == 1) {
int lo, hi; cin >> lo >> hi;
auto [l, m, r] = spliti(treap, lo - 1, hi);
treap = merge(l, r);
delete m;
}
if (t == 2) {
char c;
int p;
cin >> c >> p;
insi(treap, new Node {{c - 'a' + 1, c - 'a' + 1, 1}}, p - 1);
}
if (t == 3) {
int l, r; cin >> l >> r;
Value res = queryi(treap, l - 1, r);
cout << (res.hash == res.rhash ? "yes" : "no") << '\n';
}
}
delete treap;
}
Ly8gZ2VuZXJhdGVkIGF0IGNhdGVycGlsbG93LmdpdGh1Yi5pby9ieW90CgojaW5jbHVkZSA8Yml0cy9zdGRjKysuaD4KCnVzaW5nIG5hbWVzcGFjZSBzdGQ7CnVzaW5nIGxsID0gbG9uZyBsb25nOwoKLy8gY3VzdG9tIG1vbm9pZAoKY29uc3QgbGwgbW9kID0gMWU5ICsgNzsKY29uc3QgbGwgbSA9IDI3OwpsbCBtcG93KGxsIHgsIGxsIHkpIHsKICAgIGxsIHJlcyA9IDE7CiAgICB3aGlsZSAoeSkgewogICAgICAgIGlmICh5ICYgMSkgcmVzID0gKHJlcyAqIHgpICUgbW9kOwogICAgICAgIHggPSAoeCAqIHgpICUgbW9kOwogICAgICAgIHkgPj49IDE7CiAgICB9CiAgICByZXR1cm4gcmVzOwp9CgovLyBZb3UgY2FuIGltcGxlbWVudCB5b3VyIG93biBtb25vaWQgaGVyZSBmb3IgY3VzdG9tIG9wZXJhdGlvbnMuCnN0cnVjdCBWYWx1ZSB7CiAgICBsbCBoYXNoLCByaGFzaCwgc2l6ZTsKICAgIFZhbHVlIG9wZXJhdG9yKyhjb25zdCBWYWx1ZSYgb3RoKSBjb25zdCB7CiAgICAgICAgVmFsdWUgcmVzIHt9OwogICAgICAgIHJlcy5oYXNoID0gKChoYXNoICogbXBvdygyNywgb3RoLnNpemUpKSAlIG1vZCArIG90aC5oYXNoKSAlIG1vZDsKICAgICAgICByZXMucmhhc2ggPSAocmhhc2ggKyAob3RoLnJoYXNoICogbXBvdygyNywgc2l6ZSkpICUgbW9kKSAlIG1vZDsKICAgICAgICByZXMuc2l6ZSA9IHNpemUgKyBvdGguc2l6ZTsKICAgICAgICByZXR1cm4gcmVzOwogICAgfQp9OwoKY29uc3QgVmFsdWUgdmlkID0gezAsIDAsIDB9OwoKLy8gZW5kIGN1c3RvbSBjb2RlCgptdDE5OTM3IG10KGNocm9ubzo6c3RlYWR5X2Nsb2NrOjpub3coKS50aW1lX3NpbmNlX2Vwb2NoKCkuY291bnQoKSk7CnVzaW5nIHB0ciA9IHN0cnVjdCBOb2RlKjsKCnN0cnVjdCBOb2RlIHsKICAgIFZhbHVlIHZhbDsKICAgIFZhbHVlIGFnZzsKCiAgICBpbnQgc3o7CiAgICBpbnQgcHJpOwogICAgcHRyIGwsIHI7CgogICAgTm9kZSgpIHsKICAgICAgICBwcmkgPSBtdCgpOwogICAgICAgIHZhbCA9IHZpZDsKICAgICAgICBhZ2cgPSB2aWQ7CiAgICAgICAgc3ogPSAxOwogICAgICAgIGwgPSByID0gbnVsbHB0cjsKICAgIH0KCiAgICBOb2RlKFZhbHVlIHZhbCkgOiB2YWwodmFsKSwgYWdnKHZhbCkgewogICAgICAgIHByaSA9IG10KCk7CiAgICAgICAgc3ogPSAxOwogICAgICAgIGwgPSByID0gbnVsbHB0cjsKICAgIH0KCiAgICB+Tm9kZSgpIHsKICAgICAgICBkZWxldGUgbDsKICAgICAgICBkZWxldGUgcjsKICAgIH0KfTsKCmludCBzeihwdHIgbikgeyByZXR1cm4gbiA/IG4tPnN6IDogMDsgfTsKVmFsdWUgYWdnKHB0ciBuKSB7IHJldHVybiBuID8gbi0+YWdnIDogdmlkOyB9CgpwdHIgcHVsbChwdHIgbikgewogICAgaWYgKCFuKSByZXR1cm4gbnVsbHB0cjsKICAgIG4tPnN6ID0gc3oobi0+bCkgKyAxICsgc3oobi0+cik7CiAgICBuLT5hZ2cgPSBhZ2cobi0+bCkgKyBuLT52YWwgKyBhZ2cobi0+cik7CiAgICByZXR1cm4gbjsKfQoKcHRyIG1lcmdlKHB0ciBsLCBwdHIgcikgewogICAgaWYgKCFsIHx8ICFyKSByZXR1cm4gbCA/IGwgOiByOwogICAgaWYgKGwtPnByaSA+IHItPnByaSkgcmV0dXJuIGwtPnIgPSBtZXJnZShsLT5yLCByKSwgcHVsbChsKTsKICAgIGVsc2UgcmV0dXJuIHItPmwgPSBtZXJnZShsLCByLT5sKSwgcHVsbChyKTsKfQoKLy8gWy1pbmYsIGkpIGFuZCBbaSwgaW5mXQpwYWlyPHB0ciwgcHRyPiBzcGxpdGkocHRyIG4sIGludCBpKSB7CiAgICBpZiAoIW4pIHJldHVybiB7bnVsbHB0ciwgbnVsbHB0cn07CiAgICBpZiAoaSA8PSBzeihuLT5sKSkgewogICAgICAgIGF1dG8gW2wsIHJdID0gc3BsaXRpKG4tPmwsIGkpOwogICAgICAgIG4tPmwgPSByOwogICAgICAgIHJldHVybiB7bCwgcHVsbChuKX07CiAgICB9IGVsc2UgewogICAgICAgIGF1dG8gW2wsIHJdID0gc3BsaXRpKG4tPnIsIGkgLSAxIC0gc3oobi0+bCkpOwogICAgICAgIG4tPnIgPSBsOwogICAgICAgIHJldHVybiB7cHVsbChuKSwgcn07CiAgICB9Cn0KCi8vIGN1dHMgb3V0IFtsbywgaGkpCnR1cGxlPHB0ciwgcHRyLCBwdHI+IHNwbGl0aShwdHIgbiwgaW50IGxvLCBpbnQgaGkpIHsKICAgIGF1dG8gW2xtLCByXSA9IHNwbGl0aShuLCBoaSk7CiAgICBhdXRvIFtsLCBtXSA9IHNwbGl0aShsbSwgbG8pOwogICAgcmV0dXJuIHtsLCBtLCByfTsKfQoKLy8gaW5zZXJ0cyBub2RlIHN1Y2ggdGhhdCBpdCB3aWxsIGJlIGF0IGluZGV4IGkuIG9ubHkgaW5zZXJ0IHNpbmdsZSBub2Rlcwp2b2lkIGluc2kocHRyJiBuLCBwdHIgaXQsIGludCBpKSB7CiAgICBpZiAoIW4pIHsgbiA9IGl0OyByZXR1cm47IH0KICAgIGlmIChuLT5wcmkgPCBpdC0+cHJpKSB7CiAgICAgICAgYXV0byBbbCwgcl0gPSBzcGxpdGkobiwgaSk7CiAgICAgICAgaXQtPmwgPSBsLCBpdC0+ciA9IHIsIG4gPSBpdDsKICAgIH0gZWxzZSBpZiAoaSA8PSBzeihuLT5sKSkgaW5zaShuLT5sLCBpdCwgaSk7CiAgICBlbHNlIGluc2kobi0+ciwgaXQsIGkgLSAxIC0gc3oobi0+bCkpOwogICAgcHVsbChuKTsKfQoKVmFsdWUgcXVlcnlpKHB0ciBuLCBpbnQgbG8sIGludCBoaSkgewogICAgaWYgKCFuIHx8IGxvID49IHN6KG4pIHx8IGhpIDw9IDApIHJldHVybiB2aWQ7CiAgICBpZiAobG8gPD0gMCAmJiBzeihuKSA8PSBoaSkgcmV0dXJuIG4tPmFnZzsKICAgIHJldHVybiBxdWVyeWkobi0+bCwgbG8sIGhpKSArIChsbyA8PSBzeihuLT5sKSAmJiBzeihuLT5sKSA8IGhpID8gbi0+dmFsIDogdmlkKSArIHF1ZXJ5aShuLT5yLCBsbyAtIDEgLSBzeihuLT5sKSwgaGkgLSAxIC0gc3oobi0+bCkpOwp9Cgp2b2lkIGhlYXBpZnkocHRyIG4pIHsKICAgIGlmICghbikgcmV0dXJuOwogICAgcHRyIG14ID0gbjsKICAgIGlmIChuLT5sICYmIG4tPmwtPnByaSA+IG14LT5wcmkpIG14ID0gbi0+bDsKICAgIGlmIChuLT5yICYmIG4tPnItPnByaSA+IG14LT5wcmkpIG14ID0gbi0+cjsKICAgIGlmIChteCAhPSBuKSBzd2FwKG4tPnByaSwgbXgtPnByaSksIGhlYXBpZnkobXgpOwp9CgpwdHIgYnVpbGQodmVjdG9yPHB0cj4mIG5zLCBpbnQgbCA9IDAsIGludCByID0gLTY5KSB7CiAgICBpZiAociA9PSAtNjkpIHIgPSAoaW50KSBucy5zaXplKCkgLSAxOwogICAgaWYgKGwgPiByKSByZXR1cm4gbnVsbHB0cjsKICAgIGlmIChsID09IHIpIHJldHVybiBuc1tsXTsKICAgIGludCBtID0gKGwgKyByKSAvIDI7CiAgICBuc1ttXS0+bCA9IGJ1aWxkKG5zLCBsLCBtIC0gMSk7CiAgICBuc1ttXS0+ciA9IGJ1aWxkKG5zLCBtICsgMSwgcik7CiAgICBoZWFwaWZ5KG5zW21dKTsKICAgIHJldHVybiBwdWxsKG5zW21dKTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIE9wPgp2b2lkIHRvdXIocHRyIG4sIE9wIG9wKSB7CiAgICBzdGFjazxwdHI+IHN0azsKICAgIHdoaWxlIChuIHx8ICFzdGsuZW1wdHkoKSkgewogICAgICAgIGZvciAoOyBuOyBuID0gbi0+bCkgc3RrLnB1c2gobik7CiAgICAgICAgbiA9IHN0ay50b3AoKTsgc3RrLnBvcCgpOwogICAgICAgIG9wKG4pOwogICAgICAgIG4gPSBuLT5yOwogICAgfQp9CgovKgoKLSBpbmNsdWRlIG1lcmdlCi0gaW5jbHVkZSAzLXdheSBzcGxpdCBieSBpbmRleCAoYW5kIHNpemUsIGFuZCBzcGxpdCBieSBpbmRleCkKLSBpbmNsdWRlIHBvaW50IGluc2VydCBieSBpbmRleCAKLSBpbmNsdWRlIGJ1aWxkIChhbmQgaGVhcGlmeSkKLSBpbmNsdWRlIHRvdXIKLSBpbmNsdWRlIHJhbmdlIHF1ZXJpZXMgKGFuZCByYW5nZSBhZ2dyZWdhdGVzKQoKKi8KCm1haW4oKSB7CiAgICBjaW4udGllKDApLT5zeW5jX3dpdGhfc3RkaW8oMCk7CiAgICAKICAgIGludCBuLCBxOyBjaW4gPj4gbiA+PiBxOwogICAgc3RyaW5nIHN0OyBjaW4gPj4gc3Q7CgogICAgdmVjdG9yPHB0cj4gbnMobik7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewogICAgICAgIG5zW2ldID0gbmV3IE5vZGUoe3N0W2ldIC0gJ2EnICsgMSwgc3RbaV0gLSAnYScgKyAxLCAxfSk7CiAgICB9CiAgICBwdHIgdHJlYXAgPSBidWlsZChucyk7CgogICAgd2hpbGUgKHEtLSkgewogICAgICAgIGludCB0OyBjaW4gPj4gdDsKICAgICAgICBpZiAodCA9PSAxKSB7CiAgICAgICAgICAgIGludCBsbywgaGk7IGNpbiA+PiBsbyA+PiBoaTsKICAgICAgICAgICAgYXV0byBbbCwgbSwgcl0gPSBzcGxpdGkodHJlYXAsIGxvIC0gMSwgaGkpOwogICAgICAgICAgICB0cmVhcCA9IG1lcmdlKGwsIHIpOwogICAgICAgICAgICBkZWxldGUgbTsKICAgICAgICB9CiAgICAgICAgaWYgKHQgPT0gMikgewogICAgICAgICAgICBjaGFyIGM7CiAgICAgICAgICAgIGludCBwOwogICAgICAgICAgICBjaW4gPj4gYyA+PiBwOwogICAgICAgICAgICBpbnNpKHRyZWFwLCBuZXcgTm9kZSB7e2MgLSAnYScgKyAxLCBjIC0gJ2EnICsgMSwgMX19LCBwIC0gMSk7CiAgICAgICAgfQogICAgICAgIGlmICh0ID09IDMpIHsKICAgICAgICAgICAgaW50IGwsIHI7IGNpbiA+PiBsID4+IHI7CiAgICAgICAgICAgIFZhbHVlIHJlcyA9IHF1ZXJ5aSh0cmVhcCwgbCAtIDEsIHIpOwogICAgICAgICAgICBjb3V0IDw8IChyZXMuaGFzaCA9PSByZXMucmhhc2ggPyAieWVzIiA6ICJubyIpIDw8ICdcbic7CiAgICAgICAgfQogICAgfQogICAgZGVsZXRlIHRyZWFwOwp9