import std.algorithm, std.conv, std.range, std.stdio, std.string; const mod = 10^^9+7; alias mint = FactorRing!mod; void main() { auto n = readln.chomp.to!int; auto m = new mint[][][](n, 4, 4); foreach (i; 0..n) m[i][0][0] = m[i][1][3] = m[i][2][3] = m[i][3][3] = 1; auto u = new mint[][](4, 4); foreach (i; 0..4) u[i][i] = 1; auto st = SegmentTree!(mint[][], matMul)(m, u); auto q = readln.chomp.to!int; foreach (_; 0..q) { auto rd = readln.splitter; auto c = rd.front; rd.popFront(); auto i = rd.front.to!int; rd.popFront(); switch (c) { case "x": auto v = mint(rd.front.to!int); m[n-i-1][0][2] = v; st[n-i-1] = m[n-i-1]; break; case "y": auto v = mint(rd.front.to!int); m[n-i-1][1][1] = v; m[n-i-1][2][1] = v*2; m[n-i-1][2][2] = v*v; st[n-i-1] = m[n-i-1]; break; case "a": auto r = st[$-i..$], ans = mint(0); foreach (j; 0..4) ans += r[0][j]; writeln(ans); break; default: assert(0); } } } T[][] matMul(T)(const T[][] a, const T[][] b) { auto l = b.length, m = a.length, n = b[0].length; auto c = new T[][](m, n); foreach (i; 0..m) { static if (T.init != 0) c[i][] = 0; foreach (j; 0..n) foreach (k; 0..l) c[i][j] += a[i][k] * b[k][j]; } return c; } struct SegmentTree(T, alias pred = "a + b") { import core.bitop, std.functional; alias predFun = binaryFun!pred; const size_t n, an; T[] buf; T unit; this(size_t n, T unit = T.init) { this.n = n; this.unit = unit; an = (1 << ((n - 1).bsr + 1)); buf = new T[](an * 2); if (T.init != unit) { buf[] = unit; } } this(T[] init, T unit = T.init) { this(init.length, unit); buf[an..an+n][] = init[]; foreach_reverse (i; 1..an) buf[i] = predFun(buf[i*2], buf[i*2+1]); } void opIndexAssign(T val, size_t i) { buf[i += an] = val; while (i /= 2) buf[i] = predFun(buf[i * 2], buf[i * 2 + 1]); } pure T opSlice(size_t l, size_t r) { l += an; r += an; T r1 = unit, r2 = unit; while (l != r) { if (l % 2) r1 = predFun(r1, buf[l++]); if (r % 2) r2 = predFun(buf[--r], r2); l /= 2; r /= 2; } return predFun(r1, r2); } pure size_t opDollar() { return n; } pure T opIndex(size_t i) { return buf[i + an]; } } struct FactorRing(int m, bool pos = false) { version(BigEndian) { union { long vl; struct { int vi2; int vi; } } } else { union { long vl; int vi; } } static init() { return FactorRing!(m, pos)(0); } @property int toInt() { return vi; } alias toInt this; this(int v) { vi = v; } this(int v, bool runMod) { vi = runMod ? mod(v) : v; } this(long v) { vi = mod(v); } ref FactorRing!(m, pos) opAssign(int v) { vi = v; return this; } pure auto mod(int v) const { static if (pos) return v % m; else return (v % m + m) % m; } pure auto mod(long v) const { static if (pos) return cast(int)(v % m); else return cast(int)((v % m + m) % m); } static if (!pos) { pure auto opUnary(string op: "-")() const { return FactorRing!(m, pos)(mod(-vi)); } } static if (m < int.max / 2) { pure auto opBinary(string op: "+")(int rhs) const { return FactorRing!(m, pos)(mod(vi + rhs)); } pure auto opBinary(string op: "-")(int rhs) const { return FactorRing!(m, pos)(mod(vi - rhs)); } } else { pure auto opBinary(string op: "+")(int rhs) const { return FactorRing!(m, pos)(mod(vl + rhs)); } pure auto opBinary(string op: "-")(int rhs) const { return FactorRing!(m, pos)(mod(vl - rhs)); } } pure auto opBinary(string op: "*")(int rhs) const { return FactorRing!(m, pos)(mod(vl * rhs)); } pure auto opBinary(string op)(FactorRing!(m, pos) rhs) const if (op == "+" || op == "-" || op == "*") { return opBinary!op(rhs.vi); } static if (m < int.max / 2) { auto opOpAssign(string op: "+")(int rhs) { vi = mod(vi + rhs); } auto opOpAssign(string op: "-")(int rhs) { vi = mod(vi - rhs); } } else { auto opOpAssign(string op: "+")(int rhs) { vi = mod(vl + rhs); } auto opOpAssign(string op: "-")(int rhs) { vi = mod(vl - rhs); } } auto opOpAssign(string op: "*")(int rhs) { vi = mod(vl * rhs); } auto opOpAssign(string op)(FactorRing!(m, pos) rhs) if (op == "+" || op == "-" || op == "*") { return opOpAssign!op(rhs.vi); } }