import std; void main () { int N, Q; readln.read(N, Q); string S = readln.chomp; auto H = new int[](Q); auto W = new int[](Q); auto P = new int[](Q); foreach (i; 0 .. Q) { readln.read(H[i], W[i], P[i]); } // x軸側とy軸側で初めてH[i], W[i]に到達するマス数のmin // 累積和 + 二分探索 // 右端が左端の左に来ないように2倍に伸ばす auto xacc = new int[](2 * N + 1); auto yacc = new int[](2 * N + 1); foreach (i; 0 .. 2 * N) { int xv = S[i % N] == 'D' ? 1 : 0; int yv = xv ^ 1; xacc[i + 1] = xacc[i] + xv; yacc[i + 1] = yacc[i] + yv; } auto ans = new int[](Q); foreach (i; 0 .. Q) { bool f (long x) { long xval = xacc[N] * (x / N); xval += xacc[P[i] + (x % N)] - xacc[P[i]]; long yval = yacc[N] * (x / N); yval += yacc[P[i] + (x % N)] - yacc[P[i]]; return H[i] <= xval || W[i] <= yval; } ans[i] = (P[i] + bsearch!(f)(10L ^^ 15, 0).value) % N; } writefln("%(%s\n%)", ans); } void read (T...) (string S, ref T args) { import std.conv : to; import std.array : split; auto buf = S.split; foreach (i, ref arg; args) { arg = buf[i].to!(typeof(arg)); } } import std.traits : isIntegral; import std.int128 : Int128; class NoTrueRangeException: Exception { import std.exception: basicExceptionCtors; mixin basicExceptionCtors; } class BsearchException: Exception { import std.exception: basicExceptionCtors; mixin basicExceptionCtors; } struct BsearchResult (T) { import std.format: format; private bool has_value = true; private T l, r; private T _value; this (T _l, T _r) { this.l = _l; this.r = _r; this.has_value = false; } this (T _l, T _r, T _value) { this.l = _l; this.r = _r; this._value = _value; } bool empty () { return !this.has_value; } T value () { if (this.empty()) { throw new NoTrueRangeException( format("No true condition found in the range [%s, %s].", l, r)); } return _value; }; } BsearchResult!T bsearch (alias func, T) (T l, T r) if ((isIntegral!(T) || is(T == Int128)) && !is(T == byte) && !is(T == ubyte) && !is(T == short) && !is(T == ushort)) { import std.traits : isCallable, ReturnType, Parameters; import std.meta : AliasSeq; static assert(isCallable!(func)); static assert(is(ReturnType!(func) == bool)); static assert(is(Parameters!(func) == AliasSeq!(T))); import std.algorithm.comparison : min, max; T L = l, R = r; if (l == r) { if (func(l)) return BsearchResult!(T)(L, R, l); return BsearchResult!(T)(L, R); } while (min(l, r) + 1 < max(l, r)) { T m = midpoint(l, r); if (func(m)) { l = m; } else { r = m; } } bool lb = func(l); if (!lb) return BsearchResult!(T)(L, R); bool rb = func(r); if (rb) return BsearchResult!(T)(L, R, r); if (!rb) return BsearchResult!(T)(L, R, l); throw new BsearchException(format("This code path should never be reached. l: %s, r: %s.", L, R)); } T midpoint (T) (T a, T b) if (isIntegral!(T) || is(T == Int128)) { static if (is(T == short) || is(T == ushort) || is(T == byte) || is(T == ubyte)) { import std.conv : to; int x = a, y = b; return midpoint(x, y).to!(T); } else { import std.math.algebraic : abs; import std.algorithm.comparison : min, max; int as = (0 <= a) ? 1 : -1, bs = (0 <= b) ? 1 : -1; if (as == bs) { if (as == 1) { return min(a, b) + (max(a, b) - min(a, b)) / 2; } return max(a, b) + (min(a, b) - max(a, b)) / 2; } return (a + b) / 2; } }