// Nikita Golikov, 2023 #include using namespace std; using uint = unsigned int; using ll = long long; using ull = unsigned long long; #ifdef GOLIKOV #include "/Users/golikovnik/contests/debug.h" #else #define debug(...) ; #endif template bool smin(A& x, B&& y) { if (y < x) { x = y; return true; } return false; } template bool smax(A& x, B&& y) { if (x < y) { x = y; return true; } return false; } int main() { #ifdef GOLIKOV assert(freopen("in", "rt", stdin)); auto _clock_start = chrono::high_resolution_clock::now(); #endif ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector a(n); for (auto& x : a) { cin >> x; } ll const INF = 1e18; struct node { bool good[2][2]{}; ll last[2][2]{}; ll lastmin[2][2]{}; ll first[2][2]{}; ll firstmin[2][2]{}; ll nfirst[2][2]{}; ll nlast[2][2]{}; ll add{}; bool neutral = true; node() = default; node(int x) { neutral = false; for (int tl = 0; tl < 2; ++tl) { for (int tr = 0; tr < 2; ++tr) { good[tl][tr] = 1; if (tl && tr) { last[tl][tr] = lastmin[tl][tr] = first[tl][tr] = firstmin[tl][tr] = x; nfirst[tl][tr] = nlast[tl][tr] = INF; } else { last[tl][tr] = lastmin[tl][tr] = first[tl][tr] = firstmin[tl][tr] = nfirst[tl][tr] = nlast[tl][tr] = INF; } } } } node operator+(node const& other) const { if (neutral) { return other; } if (other.neutral) { return *this; } node res{}; res.neutral = false; for (int tl = 0; tl < 2; ++tl) { for (int tr = 0; tr < 2; ++tr) { if (first[tl][1] == INF) { int skip = first[1][1] == other.first[1][1]; res.good[tl][tr] = other.good[!skip][tr]; res.last[tl][tr] = other.last[!skip][tr]; res.lastmin[tl][tr] = other.lastmin[!skip][tr]; res.nlast[tl][tr] = other.nlast[!skip][tr]; res.first[tl][tr] = other.first[!skip][tr]; res.firstmin[tl][tr] = other.firstmin[!skip][tr]; res.nfirst[tl][tr] = other.nfirst[!skip][tr]; continue; } if (other.first[1][tr] == INF) { int skip = other.first[1][1] == last[1][1]; res.good[tl][tr] = good[tl][!skip]; res.last[tl][tr] = last[tl][!skip]; res.lastmin[tl][tr] = lastmin[tl][!skip]; res.nlast[tl][tr] = nlast[tl][!skip]; res.first[tl][tr] = first[tl][!skip]; res.firstmin[tl][tr] = firstmin[tl][!skip]; res.nfirst[tl][tr] = nfirst[tl][!skip]; continue; } res.last[tl][tr] = other.last[1][tr]; res.first[tl][tr] = first[tl][1]; res.nfirst[tl][tr] = nfirst[tl][1] == INF ? (other.first[1][tr] == first[tl][1] ? other.nfirst[1][tr] : other.first[1][tr]) : nfirst[tl][1]; res.nlast[tl][tr] = other.nlast[1][tr] == INF ? (last[tl][1] == other.last[1][tr] ? nlast[tl][1] : last[tl][1]) : other.nlast[1][tr]; auto b = last[tl][1]; auto a = nlast[tl][1]; auto c = other.first[1][tr]; auto d = other.nfirst[1][tr]; if (b == c) { bool is = a > b && b < d; if (is) { res.good[tl][tr] = good[tl][0] && lastmin[tl][0] > b && b < other.firstmin[0][tr] && other.good[0][tr]; res.lastmin[tl][tr] = other.lastmin[0][tr] == INF ? b : other.lastmin[0][tr]; res.firstmin[tl][tr] = firstmin[tl][0] == INF ? b : firstmin[tl][0]; } else { res.good[tl][tr] = good[tl][0] && (lastmin[tl][0] == INF || firstmin[0][tr] == INF || lastmin[tl][0] < other.firstmin[0][tr]) && other.good[0][tr]; res.lastmin[tl][tr] = other.lastmin[0][tr] == INF ? lastmin[tl][0] : other.lastmin[0][tr]; res.firstmin[tl][tr] = firstmin[tl][0] == INF ? other.firstmin[0][tr] : firstmin[tl][0]; } } else if (b > c) { res.good[tl][tr] = good[tl][0] && (lastmin[tl][0] == INF || lastmin[tl][0] < other.firstmin[1][tr]) && other.good[1][tr]; res.lastmin[tl][tr] = other.lastmin[1][tr]; res.firstmin[tl][tr] = firstmin[tl][0] == INF ? other.firstmin[1][tr] : firstmin[tl][0]; } else { assert(b < c); res.good[tl][tr] = good[tl][1] && (other.firstmin[0][tr] == INF || lastmin[tl][1] < other.firstmin[0][tr]) && other.good[0][tr]; res.lastmin[tl][tr] = other.lastmin[0][tr] == INF ? lastmin[tl][1] : other.lastmin[0][tr]; res.firstmin[tl][tr] = firstmin[tl][1]; } } } return res; } void apply(ll d) { add += d; for (int x = 0; x < 2; ++x) { for (int y = 0; y < 2; ++y) { if (last[x][y] != INF) last[x][y] += d; if (lastmin[x][y] != INF) lastmin[x][y] += d; if (first[x][y] != INF) first[x][y] += d; if (firstmin[x][y] != INF) firstmin[x][y] += d; if (nlast[x][y] != INF) nlast[x][y] += d; if (nfirst[x][y] != INF) nfirst[x][y] += d; } } } }; int pw = 1; while (pw < n) pw *= 2; vector tree(2 * pw); for (int i = 0; i < n; ++i) { tree[pw + i] = node(a[i]); } for (int i = pw - 1; i > 0; --i) { tree[i] = tree[2 * i] + tree[2 * i + 1]; } auto push = [&](int v) { tree[2 * v].apply(tree[v].add); tree[2 * v + 1].apply(tree[v].add); tree[v].add = 0; }; auto Query = [&](int ql, int qr) { auto rec = [&](auto self, int v, int l, int r) -> node { if (ql >= r || l >= qr) return node(); if (ql <= l && r <= qr) return tree[v]; int m = (l + r) / 2; push(v); return self(self, 2 * v, l, m) + self(self, 2 * v + 1, m, r); }; return rec(rec, 1, 0, pw); }; auto Update = [&](int ql, int qr, int val) { auto rec = [&](auto self, int v, int l, int r) -> void { if (ql >= r || l >= qr) return; if (ql <= l && r <= qr) { tree[v].apply(val); return; } int m = (l + r) / 2; push(v); self(self, 2 * v, l, m); self(self, 2 * v + 1, m, r); tree[v] = tree[2 * v] + tree[2 * v + 1]; }; rec(rec, 1, 0, pw); }; // auto print = [&](int v, int tl, int tr) { // debug(tree[v].good[tl][tr]); // debug(tree[v].last[tl][tr]); // debug(tree[v].lastmin[tl][tr]); // debug(tree[v].first[tl][tr]); // debug(tree[v].firstmin[tl][tr]); // debug(tree[v].nlast[tl][tr]); // debug(tree[v].nfirst[tl][tr]); // }; // print(4, 1, 0); // print(5, 0, 1); // print(2); print(4); print(5); int q; cin >> q; while (q--) { string t; cin >> t; int l, r; cin >> l >> r; --l; if (t == "check") { cout << (Query(l, r).good[1][1] ? "YES" : "NO") << '\n'; } else { int v; cin >> v; Update(l, r, v); } } #ifdef GOLIKOV cerr << "Executed in " << chrono::duration_cast( chrono::high_resolution_clock::now() - _clock_start).count() << "ms." << endl; #endif return 0; }