/* このコード、と~おれ! Be accepted! ∧_∧  (。・ω・。)つ━☆・*。 ⊂   ノ    ・゜+.  しーJ   °。+ *´¨)          .· ´¸.·*´¨) ¸.·*¨)           (¸.·´ (¸.·'* ☆ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#pragma GCC target("arch=skylake-avx512") //#pragma GCC target("avx2") //#pragma GCC optimize("O3") //#pragma GCC optimize("Ofast") //#pragma GCC target("sse4") //#pragma GCC optimize("unroll-loops") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") #define repeat(i, n, m) for(int i = n; i < (m); ++i) #define rep(i, n) for(int i = 0; i < (n); ++i) #define printynl(a) printf(a ? "yes\n" : "no\n") #define printyn(a) printf(a ? "Yes\n" : "No\n") #define printYN(a) printf(a ? "YES\n" : "NO\n") #define printim(a) printf(a ? "possible\n" : "imposible\n") #define printdb(a) printf("%.50lf\n", a) #define printLdb(a) printf("%.50Lf\n", a) #define printdbd(a) printf("%.16lf\n", a) #define prints(s) printf("%s\n", s.c_str()) #define all(x) (x).begin(), (x).end() #define deg_to_rad(deg) (((deg)/360.0L)*2.0L*PI) #define rad_to_deg(rad) (((rad)/2.0L/PI)*360.0L) #define Please return #define AC 0 #define manhattan_dist(a, b, c, d) (abs(a - c) + abs(b - d)) using ll = long long; using ull = unsigned long long; constexpr int INF = 1073741823; constexpr int MINF = -1073741823; constexpr ll LINF = ll(4661686018427387903); constexpr ll MOD = 1e9 + 7; constexpr ll mod = 998244353; constexpr long double eps = 1e-6; const long double PI = acosl(-1.0L); using namespace std; void scans(string& str) { char c; str = ""; scanf("%c", &c); if (c == '\n')scanf("%c", &c); while (c != '\n' && c != -1 && c != ' ') { str += c; scanf("%c", &c); } } void scanc(char& str) { char c; scanf("%c", &c); if (c == -1)return; while (c == '\n') { scanf("%c", &c); } str = c; } double acot(double x) { return PI / 2 - atan(x); } ll LSB(ll n) { return (n & (-n)); } template inline T chmin(T& a, const T& b) { if (a > b)a = b; return a; } template inline T chmax(T& a, const T& b) { if (a < b)a = b; return a; } //cpp_int #if __has_include() #include #include using namespace boost::multiprecision; #else using cpp_int = ll; #endif //atcoder library #if __has_include() #include //using namespace atcoder; #endif /* random_device seed_gen; mt19937 engine(seed_gen()); uniform_int_distribution dist(1, 100); */ /*----------------------------------------------------------------------------------*/ /** * @brief Segment-Tree(セグメント木) * @docs docs/segment-tree.md */ template< typename Monoid, typename F > struct SegmentTree { int sz; vector< Monoid > seg; const F f; const Monoid M1; SegmentTree(int n, const F f, const Monoid& M1) : f(f), M1(M1) { sz = 1; while (sz < n) sz <<= 1; seg.assign(2 * sz, M1); } void set(int k, const Monoid& x) { seg[k + sz] = x; } void build() { for (int k = sz - 1; k > 0; k--) { seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]); } } void update(int k, const Monoid& x) { k += sz; seg[k] = x; while (k >>= 1) { seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]); } } Monoid query(int a, int b) { Monoid L = M1, R = M1; for (a += sz, b += sz; a < b; a >>= 1, b >>= 1) { if (a & 1) L = f(L, seg[a++]); if (b & 1) R = f(seg[--b], R); } return f(L, R); } Monoid operator[](const int& k) const { return seg[k + sz]; } template< typename C > int find_subtree(int a, const C& check, Monoid& M, bool type) { while (a < sz) { Monoid nxt = type ? f(seg[2 * a + type], M) : f(M, seg[2 * a + type]); if (check(nxt)) a = 2 * a + type; else M = nxt, a = 2 * a + 1 - type; } return a - sz; } template< typename C > int find_first(int a, const C& check) { Monoid L = M1; if (a <= 0) { if (check(f(L, seg[1]))) return find_subtree(1, check, L, false); return -1; } int b = sz; for (a += sz, b += sz; a < b; a >>= 1, b >>= 1) { if (a & 1) { Monoid nxt = f(L, seg[a]); if (check(nxt)) return find_subtree(a, check, L, false); L = nxt; ++a; } } return -1; } template< typename C > int find_last(int b, const C& check) { Monoid R = M1; if (b >= sz) { if (check(f(seg[1], R))) return find_subtree(1, check, R, true); return -1; } int a = sz; for (b += sz; a < b; a >>= 1, b >>= 1) { if (b & 1) { Monoid nxt = f(seg[--b], R); if (check(nxt)) return find_subtree(b, check, R, true); R = nxt; } } return -1; } }; template< typename Monoid, typename F > SegmentTree< Monoid, F > get_segment_tree(int N, const F& f, const Monoid& M1) { return { N, f, M1 }; } /* * @title Mo's Algorithm * @docs kyopro/docs/mo.md */ template struct mo { int sqn, q, l, r, p; T ret; vector> query; vector ans; mo(const int& n, const int& q) : sqn((int)std::sqrt(n)), q(q), l(0), r(0), p(0), ret(get_segment_tree(26, plus(), 0)), query(q), ans(q) {} inline void insert(const int& l, const int& r) { query[p] = { l, r, p }; ++p; } inline void read(const bool& oneindexed) { for (auto& [left, right, po, idx] : query) { scanf("%d%d%d", &left, &right, &po); if (oneindexed)--left; idx = p++; } } void build() { sort(all(query), [&](const tuple& a, const tuple& b) { if (get<0>(a) / sqn != get<0>(b) / sqn)return get<0>(a) < get<0>(b); return get<1>(a) < get<1>(b); }); } void run(const ADD_LEFT& add_left, const ADD_RIGHT& add_right, const DEL_LEFT& del_left, const DEL_RIGHT& del_right, const REM& rem) { for (const auto& [ql, qr, p, qo] : query) { while (l > ql)add_left(--l, ret); while (r < qr)add_right(r++, ret); while (l < ql)del_left(l++, ret); while (r > qr)del_right(--r, ret); rem(qo, ans, ret, p); } } void run(const ADD_LEFT& add, const DEL_LEFT& del, const REM& rem) { run(add, add, del, del, rem); } char operator [](const int& idx) { return ans[idx]; } void allrun(const bool& oneindexed, const ADD_LEFT& add_left, const ADD_RIGHT& add_right, const DEL_LEFT& del_left, const DEL_RIGHT& del_right, const REM& rem) { read(oneindexed); build(); run(add_left, add_right, del_left, del_right, rem); } void allrun(const bool& oneindexed, const ADD_LEFT& add, const DEL_LEFT& del, const REM& rem) { allrun(oneindexed, add, add, del, del, rem); } }; int main() { int n, q; scanf("%d%d", &n, &q); string s, t; scans(s); auto seg = get_segment_tree(26, plus(), 0); seg.build(); auto add = [&](const int& idx, decltype(seg)& ret) { ret.update(s[idx] - 'a', ret[s[idx] - 'a'] + 1); }; auto del = [&](const int& idx, decltype(seg)& ret) { ret.update(s[idx] - 'a', ret[s[idx] - 'a'] - 1); }; auto rem = [&](const int& num, vector& ans, decltype(seg)& ret, const int& x) { int idx = ret.find_first(0, [&](const int& aa) {return aa >= x; }); ans[num] = 'a' + idx; }; mo m(n, q); m.allrun(true, add, del, rem); rep(i, q)printf("%c\n", m[i]); Please AC; }