#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; #if __has_include() #include using namespace atcoder; #endif #define GET_MACRO(_1, _2, _3, NAME, ...) NAME #define _rep(i, n) _rep2(i, 0, n) #define _rep2(i, a, b) for(int i = (int)(a); i < (int)(b); i++) #define rep(...) GET_MACRO(__VA_ARGS__, _rep2, _rep)(__VA_ARGS__) #define all(x) (x).begin(), (x).end() #define rall(x) (x).rbegin(), (x).rend() using i64 = long long; template bool chmin(T& a, const U& b) { return (b < a) ? (a = b, true) : false; } template bool chmax(T& a, const U& b) { return (b > a) ? (a = b, true) : false; } inline void YesNo(bool f) { std::cout << (f? "Yes": "No") << std::endl; } templateistream& operator>>(istream&i,vector&v){rep(j,v.size())i>>v[j];return i;} templatestring join(vector&v){stringstream s;rep(i,v.size())s<<' '<ostream& operator<<(ostream&o,vector&v){if(v.size())o<string join(vector>&vv){string s="\n";rep(i,vv.size())s+=join(vv[i])+"\n";return s;} templateostream& operator<<(ostream&o,vector>&vv){if(vv.size())o< struct SegmentTree { private: std::vector data; int _n, size; void update(int k) { data[k] = op(data[k << 1], data[k << 1 | 1]); } public: SegmentTree(int n) : SegmentTree(std::vector(n, e())) {} SegmentTree(const std::vector& v) : size(int(v.size())) { for (_n = 1; _n < size; _n *= 2); data.resize(2 * _n, e()); for (int i = 0; i < size; i++) data[i + _n] = v[i]; for (int i = _n - 1; i > 0; i--) update(i); } void set(int i, const T x) { assert(0 <= i && i < size); i += _n; data[i] = x; while (i > 1) { i >>= 1; update(i); } } void add(int i, const T x) { assert(0 <= i && i < size); i += _n; data[i] += x; while (i > 1) { i >>= 1; update(i); } } T get(int i) { assert(0 <= i && i < size); return data[i + _n]; } T prod(int l, int r) { assert(0 <= l && l <= r && r <= size); T lf = e(), rf = e(); l += _n; r += _n; while(l < r) { if (l & 1) lf = op(lf, data[l++]); if (r & 1) rf = op(data[--r], rf); l >>= 1; r >>= 1; } return op(lf, rf); } T all_prod() const { return data[1]; } template int min_left(int l, int r, T target) { assert(0 <= l && l <= r && r <= size); l += _n; r += _n; vector lv, rv; while (l < r) { if (l & 1) { lv.push_back(l++); } if (r & 1) { rv.push_back(--r); } l >>= 1; r >>= 1; } while (!rv.empty()) { lv.push_back(rv.back()); rv.pop_back(); } T now = e(); for (auto i: lv) { if (f(op(now, data[i]), target)) { while (true) { if(f(op(now, data[i]), target)) { if (i >= _n) return i - _n; i <<= 1; } else now = op(now, data[i++]); } } else now = op(now, data[i]); } return -1; } template int max_right(int l, int r, T target) { assert(0 <= l && l <= r && r <= size); l += _n; r += _n; vector lv, rv; while (l < r) { if (l & 1) { lv.push_back(l++); } if (r & 1) { rv.push_back(--r); } l >>= 1; r >>= 1; } while (!lv.empty()) { rv.push_back(lv.back()); lv.pop_back(); } T now = e(); for (auto i: rv) { if (f(op(data[i], now), target)) { while (true) { if(f(op(data[i], now), target)) { if (i >= _n) return i - _n; i <<= 1; i++; } else now = op(data[i--], now); } } else now = op(data[i], now); } return -1; } }; int op(int a, int b) { return max(a, b); } int e(){ return 0; } bool se(int a, int b) { return a > 1; } int main(){ cin.tie(nullptr); ios::sync_with_stdio(false); int n, q; cin >> n >> q; vector a(n); cin >> a; SegmentTree seg(a); while (q--) { int t, x, y; cin >> t >> x >> y; x--; if (t == 1) { seg.set(x, y); } else { if (seg.prod(x, y) > 1) { auto z = seg.max_right(x, y, 0); assert(z != -1); auto w = y - z + 1; cout << (w & 1? 'S': 'F') << "\n"; } else { cout << ((y - x) & 1? 'F': 'S') << "\n"; } } } }