Problem:
Passport
A new planet has been found that looks just like Earth. Each planet has countries numbered from $1$ to $N$. These countries are connected by rail and airlines. If there is an air route between country $i$ and country $j$ that satisfies $i
When you enter each country, you will have the first letter of that country written in your passport. The first letter is a capital letter from 'A' to 'Z'. When you arrived on this planet, you entered country $1$. You are planning to travel in such a way that the string of letters written between your entry into country $1$ and your travel to country $N$, arranged in the order in which you entered the country, is the smallest in dictionary order (the order in which words are arranged in an English-Japanese dictionary).
The first letter of the country and the airline route information are given. Write a program that outputs the string written in the passport when you travel by choosing a route so that the string made by arranging the words in the order they entered the country is the smallest in the lexical order.
Input
The input is given in the following form.
$N$ $M$
$c_1$ $c_2$ ... $c_N$
$u_1$ $v_1$
$u_2$ $v_2$
:
$u_M$ $v_M$
In the first line, the number of countries $N$ ($2 \leq N \leq 300,000$) and the number of airline routes $M$ ($0 \leq M \leq 300,000$) are given. In the second line, the first letter $c_i$ of country $i$ ($c_i$ is capitalized) is given. The following $M$ lines are the departure country $u_i$ ($1 \leq u_i < N$) and arrival country $v_i$ ($u_i < v_i \leq N$) of the $i$-th airline route.
Output
Outputs a string created by arranging the letters in the passport.
Sample Input and Output
Sample Input 1
4 1
A B C D
1 3
Sample Output 1
ABCD
Sample Input 2
6 2
A M D U Z K
1 3
3 5
Sample Output 2
ADUZK

Submitted solutions:

code_snippet: #include <iostream>
#include <iomanip>
#include <cassert>
#include <vector>
#include <algorithm>
#include <utility>
#include <numeric>
#include <tuple>
#include <ranges>
namespace ranges = std::ranges;
namespace views = std::views;
// #include "Src/Number/IntegerDivision.hpp"
// #include "Src/Utility/BinarySearch.hpp"
// #include "Src/Sequence/CompressedSequence.hpp"
// #include "Src/Sequence/RunLengthEncoding.hpp"
// #include "Src/Algebra/Group/AdditiveGroup.hpp"
// #include "Src/DataStructure/FenwickTree/FenwickTree.hpp"
// #include "Src/DataStructure/SegmentTree/SegmentTree.hpp"
// #include "Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp"
// using namespace zawa;



#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif





#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
    unsigned int _m;
    unsigned long long im;

    // @param m `1 <= m`
    explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    // @return m
    unsigned int umod() const { return _m; }

    // @param a `0 <= a < m`
    // @param b `0 <= b < m`
    // @return `a * b % m`
    unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned long long y = x * _m;
        return (unsigned int)(z - y + (z < y ? _m : 0));
    }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    // Contracts:
    // [1] s - m0 * a = 0 (mod b)
    // [2] t - m1 * a = 0 (mod b)
    // [3] s * |m1| + t * |m0| <= b
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    // by [3]: |m0| <= b/g
    // by g != b: |m0| < b/g
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

// @param n `n < 2^32`
// @param m `1 <= m < 2^32`
// @return sum_{i=0}^{n-1} floor((ai + b) / m) (mod 2^64)
unsigned long long floor_sum_unsigned(unsigned long long n,
                                      unsigned long long m,
                                      unsigned long long a,
                                      unsigned long long b) {
    unsigned long long ans = 0;
    while (true) {
        if (a >= m) {
            ans += n * (n - 1) / 2 * (a / m);
            a %= m;
        }
        if (b >= m) {
            ans += n * (b / m);
            b %= m;
        }

        unsigned long long y_max = a * n + b;
        if (y_max < m) break;
        // y_max < m * (n + 1)
        // floor(y_max / m) <= n
        n = (unsigned long long)(y_max / m);
        b = (unsigned long long)(y_max % m);
        std::swap(m, a);
    }
    return ans;
}

}  // namespace internal

}  // namespace atcoder






namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder



namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt(998244353);

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder


// using mint = atcoder::modint998244353;
using namespace std;
const long long MOD = 1000000829; //{1000000829,1000001449,1000000753,1000008349,1000008791};
using mint = atcoder::static_modint<MOD>;
const long long BASE = 31415;
int N, M;
char C[300030];
vector<int> g[300030];
int main() {
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);
    cin >> N >> M;
    for (int i = 0 ; i < N ; i++) cin >> C[i];
    for (int i = 0 ; i < M ; i++) {
        int u, v;
        cin >> u >> v;
        u--; v--;
        g[u].push_back(v);
    }
    const int D = 20;
    vector<mint> pw(D + 1, BASE);
    for (int i = 1 ; i <= D ; i++) pw[i] = pw[i - 1] * pw[i - 1];
    vector dob(N + 1, vector<int>(D + 1, N));
    vector hash(N + 1, vector<mint>(D + 1));
    for (int i = N - 1 ; i >= 0 ; i--) {
        int bst = i + 1;
        for (int v : g[i]) if (bst < N) {
            int p = bst, q = v;
            for (int j = D ; j >= 0 ; j--) {
                if (dob[p][j] < N and dob[q][j] < N and hash[p][j] == hash[q][j]) {
                    p = dob[p][j];
                    q = dob[q][j];
                }
            }
            if (p < N and q == N) swap(bst, v);
            else if (p < N and q < N) {
                if (C[p] > C[q]) swap(bst, v);
                else if (C[p] == C[q] and dob[q][0] == N) swap(bst, v);
            }
        }
        dob[i][0] = bst;
        hash[i][0] = mint::raw(C[i]);
        for (int j = 1 ; j <= D ; j++) {
            dob[i][j] = dob[dob[i][j - 1]][j - 1];
            hash[i][j] = hash[i][j - 1] + hash[dob[i][j - 1]][j - 1] * pw[j - 1];
        }
    }
    string ans;
    for (int i = 0 ; i < N ; i = dob[i][0]) ans += C[i];
    cout << ans << '\n';
}
accuracy: 1
time_ms: 380
memory_kb: 90784
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
using P=pair<ll,ll>;
template<typename T>using minque=priority_queue<T,vector<T>,greater<T>>;
template<typename T>bool chmax(T &a,const T &b){return (a<b?(a=b,true):false);}
template<typename T>bool chmin(T &a,const T &b){return (a>b?(a=b,true):false);}
template<typename T1,typename T2>istream &operator>>(istream &is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}
template<typename T1,typename T2,typename T3>istream &operator>>(istream &is,tuple<T1,T2,T3>&a){is>>std::get<0>(a)>>std::get<1>(a)>>std::get<2>(a);return is;}
template<typename T,size_t n>istream &operator>>(istream &is,array<T,n>&a){for(auto&i:a)is>>i;return is;}
template<typename T>istream &operator>>(istream &is,vector<T> &a){for(auto &i:a)is>>i;return is;}
template<typename T1,typename T2>void operator++(pair<T1,T2>&a,int n){a.first++,a.second++;}
template<typename T1,typename T2>void operator--(pair<T1,T2>&a,int n){a.first--,a.second--;}
template<typename T>void operator++(vector<T>&a,int n){for(auto &i:a)i++;}
template<typename T>void operator--(vector<T>&a,int n){for(auto &i:a)i--;}
#define overload3(_1,_2,_3,name,...) name
#define rep1(i,n) for(int i=0;i<(int)(n);i++)
#define rep2(i,l,r) for(int i=(int)(l);i<(int)(r);i++)
#define rep(...) overload3(__VA_ARGS__,rep2,rep1)(__VA_ARGS__)
#define reps(i,l,r) rep2(i,l,r)
#define all(x) x.begin(),x.end()
#define pcnt(x) __builtin_popcountll(x)
#define fin(x) return cout<<(x)<<'\n',static_cast<void>(0)
#define yn(x) cout<<((x)?"Yes\n":"No\n")
#define uniq(x) sort(all(x)),x.erase(unique(all(x)),x.end())
template<typename T>
inline int fkey(vector<T>&z,T key){return lower_bound(z.begin(),z.end(),key)-z.begin();}
ll myceil(ll a,ll b){return (a+b-1)/b;}
template<typename T,size_t n,size_t id=0>
auto vec(const int (&d)[n],const T &init=T()){
  if constexpr (id<n)return vector(d[id],vec<T,n,id+1>(d,init));
  else return init;
}
#ifdef LOCAL
#include<debug.h>
#define SWITCH(a,b) (a)
#else
#define debug(...) static_cast<void>(0)
#define debugg(...) static_cast<void>(0)
#define SWITCH(a,b) (b)
template<typename T1,typename T2>ostream &operator<<(ostream &os,const pair<T1,T2>&p){os<<p.first<<' '<<p.second;return os;}
#endif
struct Timer{
  clock_t start;
  Timer(){
    start=clock();
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout<<fixed<<setprecision(16);
  }
  inline double now(){return (double)(clock()-start)/1000;}
  #ifdef LOCAL
  ~Timer(){
    cerr<<"time:";
    cerr<<now();
    cerr<<"ms\n";
  }
  #endif
}timer;
void SOLVE();
int main(){
  int testcase=1;
  //cin>>testcase;
  for(int i=0;i<testcase;i++){
    SOLVE();
  }
}
#include<type_traits>
struct mint61{
private:
  using ull=unsigned long long;
  static constexpr ull m=(1ull<<61)-1;
  static constexpr ull mask30=(1ull<<30)-1;
  static constexpr ull mask31=(1ull<<31)-1;
  static constexpr ull mul(ull a,ull b){
    ull au=a>>31;
    ull ad=a&mask31;
    ull bu=b>>31;
    ull bd=b&mask31;
    ull mid=au*bd+ad*bu;
    ull midu=mid>>30;
    ull midd=mid&mask30;
    mid=au*bu*2+midu+(midd<<31)+ad*bd;
    midu=mid>>61,midd=mid&m;
    mid=midu+midd;
    if(mid>=m)mid-=m;
    return mid;
  }
  ull v;
public:
  using value_type=ull;
  mint61():v(0){}
  template<typename T,std::enable_if_t<std::is_signed_v<T>,std::nullptr_t> =nullptr>
  mint61(T a){
    long long v2=a%(long long)m;
    if(v2<0)v2+=(long long)m;
    v=v2;
  }
  template<typename T,std::enable_if_t<std::is_unsigned_v<T>,std::nullptr_t> =nullptr>
  mint61(T a):v(a%m){}
  static mint61 raw(ull x){
    mint61 res;
    res.v=x;
    return res;
  }
  static constexpr ull mod(){return m;}
  inline mint61 operator++(int){
    mint61 res(*this);
    *this+=mint61::raw(1);
    return res;
  }
  inline mint61 operator--(int){
    mint61 res(*this);
    *this-=mint61::raw(1);
    return res;
  }
  inline mint61 operator-(){
    mint61 res;
    if(this->v==0)return res;
    res.v=m-this->v;
    return res;
  }
  inline mint61 &operator+=(const mint61&rhs){
    v+=rhs.v;
    if(v>=m)v-=m;
    return *this;
  }
  inline mint61 &operator-=(const mint61&rhs){
    v-=rhs.v;
    if(v>=m)v+=m;
    return *this;
  }
  inline mint61 &operator*=(const mint61&rhs){
    v=mul(v,rhs.v);
    return *this;
  }
  inline mint61 &operator/=(const mint61&rhs){
    (*this)*=rhs.inv();
    return *this;
  }
  ull val()const{return v;}
  mint61 pow(ull x)const{
    mint61 res=mint61::raw(1);
    mint61 a(*this);
    while(x){
      if(x&1)res*=a;
      a*=a;
      x>>=1;
    }
    return res;
  }
  mint61 inv()const{return (*this).pow(mod()-2);}
  friend inline mint61 operator+(const mint61&lhs,const mint61&rhs){return mint61(lhs)+=rhs;}
  friend inline mint61 operator-(const mint61&lhs,const mint61&rhs){return mint61(lhs)-=rhs;}
  friend inline mint61 operator*(const mint61&lhs,const mint61&rhs){return mint61(lhs)*=rhs;}
  friend inline mint61 operator/(const mint61&lhs,const mint61&rhs){return mint61(lhs)/=rhs;}
  friend inline bool operator==(const mint61&lhs,const mint61&rhs){return lhs.v==rhs.v;}
  friend inline bool operator!=(const mint61&lhs,const mint61&rhs){return lhs.v!=rhs.v;}
  friend std::istream &operator>>(std::istream &is,mint61&a){
    is>>a.v;
    return is;
  }
  friend std::ostream &operator<<(std::ostream &os,const mint61&a){
    os<<a.v;
    return os;
  }
};
template<>
struct std::hash<mint61>{
  std::size_t operator()(mint61 x)const{
    return std::hash<unsigned long long>()(x.val());
  }
};
namespace Random{
  std::mt19937_64 mt(std::random_device{}());
  template<typename T>inline std::enable_if_t<std::is_integral_v<T>,T> get(){return mt();}
  template<typename T>inline std::enable_if_t<std::is_floating_point_v<T>,T> get(){return T(mt())/T(-1ull);}
  template<typename T>inline std::enable_if_t<std::is_integral_v<T>,T>range(T n){return mt()%n;}
  template<typename T>inline std::enable_if_t<std::is_integral_v<T>,T>range(T l,T r){return l+mt()%(r-l);}
  template<typename T>inline std::enable_if_t<std::is_integral_v<T>,std::pair<T,T>>distinct(T n){
    T l=mt()%n,r=mt()%(n-1);
    if(l==r)r++;
    if(l>r)std::swap(l,r);
    return std::make_pair(l,r);
  }
}
struct RollingHashBase{
  static mint61 base;
  static std::vector<mint61>power;
  static void resize(int n){
    if(power.size()<=n){
      int pre=power.size();
      power.resize(n+1);
      for(int i=pre;i<=n;i++)power[i]=power[i-1]*base;
    }
  }
  template<typename LHS,typename RHS>
  static int lcp(const LHS&lhs,int l1,int r1,const RHS&rhs,int l2,int r2){
    int ok=0,ng=std::min(r1-l1,r2-l2)+1;
    while(ng-ok>1){
      int mid=(ok+ng)/2;
      (lhs.get(l1,l1+mid)==rhs.get(l2,l2+mid)?ok:ng)=mid;
    }
    return ok;
  }
};
std::vector<mint61> RollingHashBase::power{1};
mint61 RollingHashBase::base=1773208334510344908;
struct PersistentRedBlackTree{
private:
  struct node{
    #ifdef LOCAL
    static constexpr int MAX=5000;
    static constexpr int BORDER=4500;
    #else
    static constexpr int MAX=6500000;
    static constexpr int BORDER=19999000;
    #endif
    static node pool[];
    static int pos;
    mint61 v;
    bool isblack;
    node *left,*right;
    int sz,rank;
    template<int need=7>
    node* push(){
      return this;
    }
    static node* create_node(mint61 vv){
      node *nd=pool+pos++;
      nd->v=vv;
      nd->isblack=true;
      nd->left=nd->right=nullptr;
      nd->sz=1;
      nd->rank=0;
      return nd;
    }
    static node* create_node(node *l,node *r,bool b){
      node *nd=pool+pos++;
      if(l){
        nd->v=l->v*RollingHashBase::power[l->sz]+r->v;
        nd->sz=l->sz+r->sz;
        nd->rank=l->rank+l->isblack;
        nd->left=l;
        nd->right=r;
      }
      else{
        nd->v=mint61();
        nd->sz=1;
        nd->rank=0;
        nd->left=nd->right=nullptr;
      }
      nd->isblack=b;
      return nd;
    }
    static node* create_node(node *l,node *r,bool b,mint61 val){
      node *nd=pool+pos++;
      nd->v=val;
      nd->left=l;
      nd->right=r;
      nd->isblack=b;
      if(l){
        nd->sz=l->sz+r->sz;
        nd->rank=l->rank+l->isblack;
      }
      else{
        nd->sz=1;
        nd->rank=0;
      }
      return nd;
    }
  };
  node *root;
  node* imerge(node *l,node *r){
    if((l->rank)<(r->rank)){
      r=r->push();
      node *c=imerge(l,r->left);
      if(r->isblack&&!c->isblack&&!c->left->isblack){
        if(r->right->isblack){
          return node::create_node(c->left,node::create_node(c->right,r->right,false),true);
        }
        else{
          r->right=r->right->push();
          return node::create_node(node::create_node(c->left,c->right,true),node::create_node(r->right->left,r->right->right,true),false);
        }
      }
      else{
        return node::create_node(c,r->right,r->isblack);
      }
    }
    else if(l->rank>r->rank){
      l=l->push();
      node *c=imerge(l->right,r);
      if(l->isblack&&!c->isblack&&!c->right->isblack){
        if(l->left->isblack){
          return node::create_node(node::create_node(l->left,c->left,false),c->right,true);
        }
        else{
          l->left=l->left->push();
          return node::create_node(node::create_node(l->left->left,l->left->right,true),node::create_node(c->left,c->right,true),false);
        }
      }
      else{
        return node::create_node(l->left,c,l->isblack);
      }
    }
    else{
      return node::create_node(l,r,false);
    }
    return nullptr;
  }
  node* imerge2(node *l,node *r){
    if(!l)return r;
    if(!r)return l;
    node *nd=imerge(l,r);
    nd->isblack=true;
    return nd;
  }
  template<int need=1>
  node* as_root(node *nd){
    if(!nd||nd->isblack)return nd;
    if constexpr(need)return node::create_node(nd->left,nd->right,true,nd->v);
    else{
      nd->isblack=true;
      return nd;
    }
  }
  template<int need,int top=1>
  std::pair<node*,node*>isplit(node *nd,int k){
    if(k==0)return std::make_pair(nullptr,nd);
    if(k==nd->sz)return std::make_pair(nd,nullptr);
    if(k<nd->left->sz){
      nd=nd->template push<top*4+(need|1)>();
      auto [l,r]=isplit<need,0>(nd->left,k);
      if constexpr(need&2)return std::make_pair(l,imerge2(r,as_root<top>(nd->right)));
      else return std::make_pair(l,nullptr);
    }
    else if(k>nd->left->sz){
      nd=nd->template push<top*4+(need|2)>();
      auto [l,r]=isplit<need,0>(nd->right,k-nd->left->sz);
      if constexpr(need&1)return std::make_pair(imerge2(as_root<top>(nd->left),l),r);
      else return std::make_pair(nullptr,r);
    }
    else{
      nd=nd->template push<top*4+need>();
      node *res_l=nullptr,*res_r=nullptr;
      if constexpr(need&1)res_l=as_root<top>(nd->left);
      if constexpr(need&2)res_r=as_root<top>(nd->right);
      return std::make_pair(res_l,res_r);
    }
  }
  PersistentRedBlackTree(node *r):root(r){}
public:
  PersistentRedBlackTree():root(nullptr){}
  [[nodiscard]]PersistentRedBlackTree insert(int k,mint61 v){
    auto [l,r]=isplit<3>(root,k);
    node *nd=node::create_node(v);
    return PersistentRedBlackTree(imerge2(l,imerge2(nd,r)));
  }
  mint61 prod(int l,int r){
    if(l==r)return mint61();
    int prepos=node::pos;
    auto [left,right]=isplit<3>(root,l);
    auto [middle,right2]=isplit<3>(right,r-l);
    node::pos=prepos;
    return middle->v;
  }
  mint61 get(int i){
    node *nd=root;
    while(nd->left){
      if(nd->left->sz>i)nd=nd->left;
      else i-=nd->left->sz,nd=nd->right;
    }
    return nd->v;
  }
  void print(){
    auto dfs=[&](auto self,node *nd)->void {
      if(nd->left)self(self,nd->left),self(self,nd->right);
      else cout<<(char)nd->v.val();
    };
    dfs(dfs,root);
    cout<<'\n';
  }
  int size()const{return root?root->sz:0;}
};
typename PersistentRedBlackTree::node PersistentRedBlackTree::node::pool[PersistentRedBlackTree::node::MAX];
int PersistentRedBlackTree::node::pos=0;
int lcp(PersistentRedBlackTree lhs,PersistentRedBlackTree rhs){
  int ok=0,ng=min(lhs.size(),rhs.size())+1;
  while(ng-ok>1){
    int mid=(ok+ng)/2;
    (lhs.prod(0,mid)==rhs.prod(0,mid)?ok:ng)=mid;
  }
  return ok;
}
void SOLVE(){
  int n,m;
  cin>>n>>m;
  vector<char>s(n);
  cin>>s;
  vector<vector<int>>to(n);
  rep(i,m){
    int u,v;
    cin>>u>>v;
    u--,v--;
    to[u].push_back(v);
  }
  vector<PersistentRedBlackTree>dp(n);
  dp[n-1]=dp[n-1].insert(0,s[n-1]);
  for(int i=n-2;i>=0;i--){
    dp[i]=dp[i+1];
    for(int j:to[i]){
      int l=lcp(dp[i],dp[j]);
      debug(i,j,l);
      if(l==dp[j].size()||(l<dp[i].size()&&dp[i].get(l).val()>dp[j].get(l).val()))dp[i]=dp[j];
    }
    dp[i]=dp[i].insert(0,s[i]);
  }
  dp[0].print();
}
accuracy: 0.18181818181818182
time_ms: 30
memory_kb: 257484
final_rank: 20

code_snippet: // AOJ #438
// Passport 2025.2.2

#include <bits/stdc++.h>
using namespace std;

using ull = unsigned long long;
const int MAXK = 20;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    int N, M;
    cin >> N >> M;
    vector<char> letter(N+1);
    for (int i = 1; i <= N; i++) cin >> letter[i];
 
    vector<vector<int>> airlines(N+1);
    for (int i = 0; i < M; i++){
        int u, v;
        cin >> u >> v;
        airlines[u].push_back(v);
    }
 
    vector<ull> p_pow(N+1, 0);
    const ull base = 131ULL;
    p_pow[0] = 1;
    for (int i = 1; i <= N; i++){
        p_pow[i] = p_pow[i-1] * base;
    }
 
    vector<int> nxt(N+1, -1);
    vector<int> Larr(N+1, 0);
 
    vector<int> jumpTable((N+1) * MAXK, -1);
    vector<ull> segTable((N+1) * MAXK, 0);
    auto getJump = [&](int i, int k) -> int {
        return jumpTable[i * MAXK + k];
    };
    auto setJump = [&](int i, int k, int val) {
        jumpTable[i * MAXK + k] = val;
    };
    auto getSeg = [&](int i, int k) -> ull {
        return segTable[i * MAXK + k];
    };
    auto setSeg = [&](int i, int k, ull val) {
        segTable[i * MAXK + k] = val;
    };
 
    auto jump_from = [&](int i, int len) -> int {
        for (int k = MAXK - 1; k >= 0; k--){
            int step = 1 << k;
            if(len >= step){
                i = getJump(i, k);
                if(i == -1) return -1;
                len -= step;
            }
        }
        return i;
    };
 
    auto get_hash = [&](int i, int len) -> ull {
        ull res = 0;
        for (int k = MAXK - 1; k >= 0; k--){
            int step = 1 << k;
            if(len >= step){
                res = res * p_pow[step] + getSeg(i, k);
                i = getJump(i, k);
                len -= step;
            }
        }
        return res;
    };
 
    auto get_char_at = [&](int i, int pos) -> char {
        int idx = jump_from(i, pos);
        return (idx == -1 ? '\0' : letter[idx]);
    };
 
    function<int(int,int)> LCP = [&](int i, int j) -> int {
        int lcp = 0;
        int p = i, q = j;
        for (int k = MAXK - 1; k >= 0; k--){
            int step = 1 << k;
            // We can jump if the remaining chain (from p and q) is at least "step" long.
            if(p != -1 && q != -1 && Larr[p] >= step && Larr[q] >= step){
                ull h1 = get_hash(p, step);
                ull h2 = get_hash(q, step);
                if(h1 == h2){
                    lcp += step;
                    p = jump_from(p, step);
                    q = jump_from(q, step);
                }
            }
        }
        return lcp;
    };
 
    auto cmp_dp = [&](int i, int j) -> int {
        if(i == j) return 0;
        int common = LCP(i, j);
        if(common >= Larr[i] || common >= Larr[j]){
            if(Larr[i] == Larr[j]) return 0;
            return (Larr[i] < Larr[j] ? -1 : 1);
        }
        char a = get_char_at(i, common);
        char b = get_char_at(j, common);
        return (a < b ? -1 : 1);
    };
 
    for (int i = N; i >= 1; i--){
        int best;
        if(i == N){
            best = -1;
        } else {
            best = i + 1;
        }
        for (int candidate : airlines[i]) {
            if(best == -1){
                best = candidate;
            } else {
                int cmpVal = cmp_dp(candidate, best);
                if(cmpVal < 0) {
                    best = candidate;
                }
            }
        }
        nxt[i] = best;
        Larr[i] = 1 + (best == -1 ? 0 : Larr[best]);
 
        setJump(i, 0, best);
        setSeg(i, 0, (ull)(letter[i] - 'A' + 1));
        for (int k = 1; k < MAXK; k++){
            int segLen = 1 << k;
            if(Larr[i] < segLen) break;
            int firstJump = getJump(i, k-1);
            if(firstJump == -1){
                setJump(i, k, -1);
                break;
            }
            int secondJump = getJump(firstJump, k-1);
            setJump(i, k, secondJump);
            ull combined = getSeg(i, k-1) * p_pow[ 1 << (k-1) ] + getSeg(firstJump, k-1);
            setSeg(i, k, combined);
        }
    }
 
    string ans;
    int cur = 1;
    while(cur != -1){
        ans.push_back(letter[cur]);
        cur = nxt[cur];
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 420
memory_kb: 94980
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

template <long long Modulus>
struct modint {
	long long x;
	constexpr modint(const long long x = 0ll) noexcept : x(x % Modulus) {}
	constexpr modint operator+(const modint rhs) const noexcept {
		return modint(*this) += rhs;
	}
	constexpr modint operator-(const modint rhs) const noexcept {
		return modint(*this) -= rhs;
	}
	constexpr modint operator*(const modint rhs) const noexcept {
		return modint(*this) *= rhs;
	}
	constexpr modint operator/(const modint rhs) const noexcept {
		return modint(*this) /= rhs;
	}
	constexpr modint &operator+=(const modint rhs) noexcept {
		x += rhs.x;
		if (x >= Modulus) {
			x -= Modulus;
		}
		return *this;
	}
	constexpr modint &operator-=(const modint rhs) noexcept {
		if (x < rhs.x) {
			x += Modulus;
		}
		x -= rhs.x;
		return *this;
	}
	constexpr modint &operator*=(const modint rhs) noexcept {
		x = x * rhs.x % Modulus;
		return *this;
	}
	constexpr modint &operator/=(modint rhs) noexcept {
		*this *= rhs.pow(Modulus - 2ll);
		return *this;
	}
	constexpr modint pow(long long t) const noexcept {
		modint a = *this, res = 1ll;
		while (t) {
			if (t & 1ll) {
				res *= a;
			}
			a *= a;
			t >>= 1ll;
		}
		return res;
	}
};
template <long long Modulus>
ostream& operator<<(ostream& os,modint<Modulus> m){
	os << m.x;
	return os;
}
using mint = modint<998244353>;
int main()
{
	cin.tie(nullptr);
	ios_base::sync_with_stdio(false);
	int n,m;
	cin >> n >> m;
	vector<char> c(n);
	for(int i = 0;i < n;i++){
		cin >> c[i];
	}
	vector<vector<int>> g(n,vector<int>());
	for(int i = 0;i < m;i++){
		int u,v;
		cin >> u >> v;
		u--;v--;
		if(u + 1 == v) continue;
		g[u].push_back(v);
	}
	for(int i = 0;i < n - 1;i++){
		g[i].push_back(i + 1);
	}
	vector<vector<int>> a(n,vector<int>(19,-1));
	vector<vector<mint>> b(n,vector<mint>(19,0));
	vector<int> ans(n,0);
	vector<mint> pw(n + 1,1);
	mint ran = 27;
	for(int i = 1;i <= n;i++){
		pw[i] = pw[i - 1] * ran;
	}
	ans[n - 1] = 1;
	b[n - 1][0] = c[n - 1] - 'A' + 1;
	auto con = [&](mint x,mint y,int s) -> mint {
		return x * pw[s] + y;
	};
	auto getnum = [&](int x,int y) -> int {
		for(int i = 0;i < 19;i++){
			if(y & (1 << i)){
				x = a[x][i];
			}
		}
		return x;
	};
	auto get = [&](int x,int y) -> mint {
		mint res = 0;
		for(int i = 0;i < 19;i++){
			if(y & (1 << i)){
				res = con(res,b[x][i],1 << i);
				x = a[x][i];
			}
		}
		return res;
	};
	auto com = [&](int x,int y) -> int {
		if(ans[x] > ans[y]) swap(x,y);
		int low = 1,high = ans[x] + 1;
		while(low < high){
			int mid = (low + high) / 2;
			if(get(x,mid).x != get(y,mid).x){
				high = mid;
			}else{
				low = mid + 1;
			}
		}
		if(low == ans[x] + 1) return x;
		int X = getnum(x,low - 1);
		int Y = getnum(y,low - 1);
		if(c[X] < c[Y]) return x;
		return y;
	};
	for(int i = n - 2;i >= 0;i--){
		char mi = 'Z';
		for(int j : g[i]){
			mi = min(mi,c[j]);
		}
		for(int j : g[i]){
			if(c[j] != mi) continue;
			if(ans[i] == 0){
				ans[i] = ans[j] + 1;
				a[i][0] = j;
			}else{
				a[i][0] = com(a[i][0],j);
				ans[i] = ans[a[i][0]] + 1;
			}
		}
		b[i][0] = c[i] - 'A' + 1;
		for(int j = 1;j < 19;j++){
			if(a[i][j - 1] == -1) continue;
			a[i][j] = a[a[i][j - 1]][j - 1];
			b[i][j] = con(b[i][j - 1],b[a[i][j - 1]][j - 1],1 << (j - 1));
		}
	}
	int now = 0;
	while(now != -1){
		cout << c[now];
		now = a[now][0];
	}
	cout << endl;
}
accuracy: 1
time_ms: 2480
memory_kb: 112724
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main()
{
	int n,m;
	cin >> n >> m;
	vector<char> c(n);
	for(int i = 0;i < n;i++){
		cin >> c[i];
	}
	vector<vector<int>> g(n,vector<int>());
	for(int i = 0;i < m;i++){
		int u,v;
		cin >> u >> v;
		u--;v--;
		if(u + 1 == v) continue;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	for(int i = 0;i < n - 1;i++){
		g[i].push_back(i + 1);
		g[i + 1].push_back(i);
	}
	vector<int> ans(n,-1);
	ans[0] = 0;
	{
		queue<int> q;
		q.push(0);
		while(ans[n - 1] == -1){
			char mi = 'Z';
			queue<int> nex;
			while(!q.empty()){
				int it = q.front();
				nex.push(it);
				q.pop();
				for(int i : g[it]){
					if(i < it) continue;
					mi = min(mi,c[i]);
				}
			}
			while(!nex.empty()){
				int it = nex.front();
				nex.pop();
				for(int i : g[it]){
					if(i < it) continue;
					if(c[i] == mi){
						ans[i] = ans[it] + 1;
						q.push(i);
					}
				}
			}
		}
	}
	string p = "";
	int now = ans[n - 1] + 1;
	for(int i = n - 1;i >= 0;i--){
		if(ans[i] == now - 1){
			now--;
			p += c[i];
		}
	}
	reverse(p.begin(),p.end());
	cout << p << endl;
}
accuracy: 0.36363636363636365
time_ms: 80
memory_kb: 11216
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main() {

  constexpr int MSB = 18;
  constexpr long long MOD = 1000000007;
  constexpr long long BASE = 998244353;
  vector<long long> base_pow(MSB+1, BASE);
  for(int i = 0; i < MSB; i++) {
    base_pow[i+1] = base_pow[i]*base_pow[i]%MOD;
  }

  int N, M;
  cin >> N >> M;
  vector<char> c(N+1, '$');
  vector<vector<int>> G(N+1);
  for(int i = 0; i < N; i++) {
    cin >> c[i];
    G[i].push_back(i+1);
  }
  for(int i = 0; i < M; i++) {
    int u, v;
    cin >> u >> v;
    G[u-1].push_back(v-1);
  }

  vector<vector<int>> dest(MSB+1, vector<int>(N+1, N));
  vector<vector<long long>> hash(MSB+1, vector<long long>(N+1, 0));
  auto mov = [&](int s, int l) -> pair<int, long long> {
    long long ret = 0;
    for(int k = MSB; k >= 0; k--) {
      if((l>>k)&1) {
        ret = (ret*base_pow[k]+hash[k][s])%MOD;
        s = dest[k][s];
      }
    }
    return make_pair(s, ret);
  };
  for(int i = N-1; i >= 0; i--) {
    int nxt = i+1;
    for(const int &j : G[i]) {
      int ok = 0, ng = N;
      while(ok+1 < ng) {
        int mid = (ok+ng)/2;
        if(mov(nxt, mid).second == mov(j, mid).second) ok = mid;
        else ng = mid;
      }
      if(c[mov(nxt, ok).first] > c[mov(j, ok).first]) nxt = j;
    }
    dest[0][i] = nxt;
    hash[0][i] = c[i];
    for(int k = 0; k < MSB; k++) {
      dest[k+1][i] = dest[k][dest[k][i]];
      hash[k+1][i] = (hash[k][i]*base_pow[k]+hash[k][dest[k][i]])%MOD;
    }
  }

  string ans;
  for(int i = 0; i < N; i = dest[0][i]) ans.push_back(c[i]);
  cout << ans << endl;

}
accuracy: 1
time_ms: 1460
memory_kb: 90140
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main() {
  int N, M;
  cin >> N >> M;
  vector<char> c(N);
  vector<vector<int>> G(N);
  for(int i = 0; i < N; i++) {
    cin >> c[i];
  }
  for(int i = 0; i < M; i++) {
    int u, v;
    cin >> u >> v;
    G[--u].push_back(--v);
  }
  for(int i = 0; i < N-1; i++) {
    G[i].push_back(i+1);
  }
  vector<string> dp(N);
  dp[N-1] = c[N-1];
  for(int i = N-2; i >= 0; i--) {
    string ep = dp[i+1];
    for(const int j : G[i]) ep = min(ep, dp[j]);
    dp[i] = c[i]+ep;
  }
  cout << dp[0] << endl;
}
accuracy: 0.3939393939393939
time_ms: 100
memory_kb: 43692
final_rank: 14

code_snippet: #include <algorithm>
#include <utility>
#include <cassert>
#include <vector>
#include <iostream>

namespace nachia{

template<class Key, class Payload>
struct Tree {
public:

struct FNode;
struct Node;

struct FNode {
    struct Node *p;
    unsigned int z;
    FNode(unsigned int _z) : p(nullptr), z(_z) {}
    struct Node *re(){ return (Node*)this; }
};

struct Iterator {
    FNode* p = nullptr;
    bool isEnd() const { return p->z == 0; }
    unsigned int index() const { return p->z ? p->re()->index() : p->p->z; }
    const typename Node::Item& operator*() const { return p->re()->kv; }
    const typename Node::Item* operator->() const { return &p->re()->kv; }
    bool operator==(Iterator r) const { return p == r.p; }
    bool operator!=(Iterator r) const { return p != r.p; }
    bool operator<(Iterator r) const { return index() < r.index(); }
    bool operator>(Iterator r) const { return index() > r.index(); }
    bool operator<=(Iterator r) const { return index() <= r.index(); }
    bool operator>=(Iterator r) const { return index() >= r.index(); }
    Iterator& operator++(){ p = p->re()->next(); return *this; }
    Iterator& operator--(){ p = (isEnd() ? p->p->back() : p->re()->prev()); return *this; }
};

struct Node : public FNode {
    static inline Node* NIL;
    unsigned int h;
    struct Item { Key key; Payload val; } kv;
    Payload sum;
    Node *l = nullptr;
    Node *r = nullptr;
    Node()
        : FNode(0), h(0)
        , kv({Key(),Payload::identity()})
        , sum(Payload::identity()) {}
    Node(Key _key, Payload p)
        : FNode(1), h(1)
        , kv({std::move(_key),p})
        , sum(p) {}
    static Node* GetNil(){
        if(!NIL){
            NIL = new Node();
            NIL->l = NIL->r = NIL->p = NIL;
        }
        return NIL;
    }
    static Node* NewNode(Key key, Payload val){
        GetNil();
        Node *res = new Node(key, val);
        res->l = res->r = res->p = NIL;
        res->z = 1;
        return res;
    }
    static Node* Construct(std::vector<std::pair<Key, Payload>> val){
        for(size_t i=0; i+1<val.size(); i++) assert(val[i].first < val[i+1].first);
        auto s = [&](auto& s, int l, int r) -> Node* {
            if(l == r) return GetNil();
            int m = (l + r) / 2;
            auto buf = NewNode(std::move(val[m].first), std::move(val[m].second));
            buf->setChildren(s(s,l,m), s(s,m+1,r));
            return buf;
        };
        return s(s, 0, (int)val.size());
    }
    void aggregate(){
        sum = kv.val;
        h = 1; this->z = 1;
        sum = l->sum + sum; this->z += l->z; h = std::max(h, l->h + 1);
        sum = sum + r->sum; this->z += r->z; h = std::max(h, r->h + 1);
    }
    void setChildren(Node* lc, Node* rc){
        l = lc; if(lc != NIL) lc->p = this;
        r = rc; if(rc != NIL) rc->p = this;
        aggregate();
    }
    // if the 2 children have unbalanced height, fix them
    Node* rebalance(){
        auto c = this;
        auto cl = c->l;
        auto cr = c->r;
        if(cl->h + 1 < cr->h){
            auto crl = cr->l;
            auto crr = cr->r;
            if(crl->h <= crr->h){
                cr->p = c->p;
                c->setChildren(cl, crl);
                cr->setChildren(c, crr);
                return cr;
            } else{
                crl->p = c->p;
                c->setChildren(cl, crl->l);
                cr->setChildren(crl->r, crr);
                crl->setChildren(c, cr);
                return crl;
            }
        }
        else if(cl->h > cr->h + 1){
            auto cll = cl->l;
            auto clr = cl->r;
            if(clr->h <= cll->h){
                cl->p = c->p;
                c->setChildren(clr, cr);
                cl->setChildren(cll, c);
                return cl;
            } else{
                clr->p = c->p;
                c->setChildren(clr->r, cr);
                cl->setChildren(cll, clr->l);
                clr->setChildren(cl, c);
                return clr;
            }
        }
        aggregate();
        return this;
    }
    // call rebalance from this node to the root
    Node* rebalanceToRoot(){
        auto c = this;
        while(c->p != NIL){
            auto cp = c->p;
            (cp->l == c ? cp->l : cp->r) = c->rebalance();
            c = cp;
        }
        return c->rebalance();
    }
    Node* next(){
        auto c = this;
        if(c->r != NIL){
            c = c->r;
            while(c->l != NIL) c = c->l;
            return c;
        }
        while(c->p->r == c) c = c->p;
        return c->p;
    }
    Node* prev(){
        auto c = this;
        if(c->l != NIL){
            c = c->l;
            while(c->r != NIL) c = c->r;
            return c;
        }
        while(c->p->l == c) c = c->p;
        return c->p;
    }
    unsigned int index(){
        auto c = this;
        if(c == NIL) return ~0u;
        unsigned int res = c->l->z;
        while(c->p != NIL){
            auto cp = c->p;
            if(cp->r == c) res += cp->l->z + 1;
            c = cp;
        }
        return res;
    }
    // kth node under this, returns alt if not exist
    Node* kth(unsigned int idx, Node* alt){
        if(idx >= this->z) return alt;
        auto c = this;
        while(true){
            if(c->l->z > idx) c = c->l;
            else if(c->l->z == idx) break;
            else{ idx -= c->l->z + 1; c = c->r; }
        }
        return c;
    }
    // most left no-less-than k under this, and the next
    std::pair<Node*, Node*> lBound(Key k){
        Node *ql = NIL;
        Node *qr = NIL;
        auto c = this;
        while(c != NIL){
            if(c->kv.key < k){ ql = c; c = c->r; }
            else{ qr = c; c = c->l; }
        }
        return std::make_pair(ql, qr);
    }
    // most left grater-than k under this, and the next
    std::pair<Node*, Node*> uBound(Key k){
        Node *ql = NIL;
        Node *qr = NIL;
        auto c = this;
        while(c != NIL){
            if(k < c->kv.key){ qr = c; c = c->l; }
            else{ ql = c; c = c->r; }
        }
        return std::make_pair(ql, qr);
    }
    // update the payload and aggregate upto root
    void set(Payload val){
        kv.val = std::move(val);
        auto c = this;
        while(c != NIL){ c->aggregate(); c = c->p; }
    }
    static Node* rootOf(Node* p){
        while(p->p != NIL) p = p->p;
        return p;
    }
    static Payload rangeSumR(Node* l){
        assert(l != NIL);
        Payload res = l->kv.val + l->r->sum;
        auto lp = l->p;
        while(lp != NIL){
            if(lp->l == l) res = res + lp->kv.val + lp->r->sum;
            l = lp; lp = l->p;
        }
        return res;
    }
    static Payload rangeSum(Node* l, Node* r){
        assert(l != NIL);
        assert(r != NIL);
        assert(l != r);
        assert(rootOf(l) == rootOf(r));
        assert(l->index() <= r->index());
        r = r->prev();
        if(l == r) return l->kv.val;
        Payload lsum = l->kv.val;
        Payload rsum = r->kv.val;
        while(l != r){
            if(l->h < r->h){
                Node* lp = l->p;
                lsum = lsum + l->r->sum;
                while(lp->l != l){ l = lp; lp = l->p; }
                if(lp == r) return lsum + rsum;
                lsum = lsum + lp->kv.val;
                l = lp;
            } else {
                Node* rp = r->p;
                rsum = r->l->sum + rsum;
                while(rp->r != r){ r = rp; rp = r->p; }
                if(rp == l) return lsum + rsum;
                rsum = rp->kv.val + rsum;
                r = rp;
            }
        }
        return lsum + rsum;
    }
    template<class Pred>
    static Node* maxRight(Node* l, Pred& pred){
        Payload q = l->kv.val;
        if(!pred(q)) return l;
        while(true){
            Payload q2 = q + l->r->sum;
            if(!pred(q2)) break;
            l = l->p;
            if(l == NIL) return NIL;
            q = q2 + l->kv.val;
            if(!pred(q)) return l;
        }
        auto c = l->r;
        while(c != NIL){
            Payload q2 = q + c->l->sum;
            if(!pred(q2)){ c = c->l; continue; }
            q = q2 + c->kv.val;
            if(!pred(q)) return c;
            c = c->r;
        }
        return NIL;
    }
    void clear(){
        if(this == NIL) return;
        l->clear(); if(l != NIL) delete(l);
        r->clear(); if(r != NIL) delete(r);
    }
    Node* insert(Node* x){
        if(this == NIL) return x;
        auto q = lBound(x->kv.key);
        if(q.first != NIL && q.first->r == NIL){
            q.first->setChildren(q.first->l, x);
            return q.first->rebalanceToRoot();
        }
        q.second->setChildren(x, q.second->r);
        return q.second->rebalanceToRoot();
    }
    Node* erase(Node* ql, Node* qr){
        auto qlp = ql->p;
        Node* res = NIL;
        if(ql->r == NIL){
            auto qll = ql->l;
            if(qll != NIL) qll->p = qlp;
            if(qlp != NIL) (qlp->l == ql ? qlp->l : qlp->r) = qll;
            res = (qlp == NIL ? qll : qlp->rebalanceToRoot());
        } else {
            assert(qr != NIL);
            assert(qr->l == NIL);
            auto qrp = qr->p;
            auto qrr = qr->r;
            if(qlp != NIL) (qlp->l == ql ? qlp->l : qlp->r) = qr;
            qr->p = qlp;
            qr->l = ql->l;
            if(qr->l != NIL) qr->l->p = qr;
            if(ql->r == qr){
                qr->aggregate();
                res = qr->rebalanceToRoot();
            } else {
                (qrp->l == qr ? qrp->l : qrp->r) = qrr;
                if(qrr != NIL) qrr->p = qrp;
                qr->r = ql->r;
                qr->r->p = qr;
                qr->aggregate();
                res = qrp->rebalanceToRoot();
            }
        }
        ql->l = ql->r = ql->p = NIL;
        ql->aggregate();
        return res;
    }
    Node* back(){
        auto c = this;
        while(c->r != NIL) c = c->r;
        return c;
    }
};

    Tree() : rt(0) { rt.p = Node::GetNil(); }
    Tree(std::vector<std::pair<Key, Payload>> init) : rt(0) { rt.p = Node::Construct(std::move(init)); }
    Iterator end(){ return {&rt}; }
    Iterator begin(){
        FNode *p = rt.p->z ? rt.p->kth(0,nullptr) : &rt;
        return {p};
    }
    void clear(){
        if(rt.p != Node::GetNil()){
            rt.p->clear();
            delete(rt.p);
            rt.p = Node::NIL;
        }
    }
    ~Tree(){ clear(); }
    int size() const { return rt.p->z; }
    bool empty() const { return rt.p == Node::NIL; }
    Payload sum(Iterator l, Iterator r, Payload ifnull){
        if(l == r) return ifnull;
        if(r == end()) return Node::rangeSumR(l.p->re());
        return Node::rangeSum(l.p->re(), r.p->re());
    }
    Iterator kth(unsigned int idx){
        auto p = root()->kth(idx, nullptr);
        return p ? Iterator{p} : end();
    }
    Iterator lBound(Key key){
        auto p = root()->lBound(std::move(key)).second;
        return p == Node::NIL ? end() : Iterator{p};
    }
    Iterator uBound(Key key){
        auto p = root()->uBound(std::move(key)).second;
        return p == Node::NIL ? end() : Iterator{p};
    }
    Iterator insert(Key k, Payload v){
        auto x = Node::NewNode(std::move(k), std::move(v));
        rt.p = root()->insert(x);
        return Iterator{ x };
    }
    Iterator erase(Iterator i){
        assert(i != end());
        auto nx = i; ++nx;
        auto nxv = nx == end() ? Node::NIL : nx.p->re();
        rt.p = root()->erase(i.p->re(), nxv);
        delete(i.p->re());
        return nx;
    }
    Iterator changeKey(Iterator i, Key k){
        assert(i != end());
        auto nx = i; ++nx;
        auto ptr = i.p->re();
        auto nxv = nx == end() ? Node::NIL : nx.p->re();
        rt.p = root()->erase(i.p->re(), nxv);
        ptr->kv.key = std::move(k);
        rt.p = root()->insert(i.p->re());
        return i;
    }
    void output(){ root()->output(); }
    
private:
    FNode rt;
    Node* root(){ return rt.p->re(); }
};

} // namespace nachia


#include <vector>
#include <algorithm>

struct Key;
struct Payload {
    static Payload identity(){ return {}; }
    Payload operator+(Payload) const { return {}; }
};
struct Key {
    char ch;
    int nx;
};

using TreeInst = nachia::Tree<Key, Payload>;
TreeInst globalTree;
std::vector<TreeInst::Iterator> globalIters;
bool operator<(Key l, Key r){
    if(l.ch != r.ch) return l.ch < r.ch;
    if(globalIters[l.nx] == globalTree.end()) return true;
    if(globalIters[r.nx] == globalTree.end()) return false;
    return globalIters[l.nx] < globalIters[r.nx];
}

int main() {
    using namespace std;
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    int N, M; cin >> N >> M;
    vector<char> C(N);
    for(int i=0; i<N; i++) cin >> C[i];
    vector<vector<int>> nxways(N);
    for(int i=0; i<M; i++){
        int u, v; cin >> u >> v; u--; v--;
        nxways[u].push_back(v);
    }

    globalIters.assign(N+1, globalTree.end());
    
    for(int i=N-1; i>=0; i--){
        int nx = i+1;
        for(int j : nxways[i]){
            if(globalIters[j] < globalIters[nx]) nx = j;
        }
        globalIters[i] = globalTree.insert({ C[i], nx }, {});
    }

    std::string res;
    auto readPos = globalIters[0];
    while(readPos != globalTree.end()){
        res.push_back(readPos->key.ch);
        readPos = globalIters[readPos->key.nx];
    }

    cout << res << '\n';
    return 0;
}
accuracy: 1
time_ms: 920
memory_kb: 41148
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;
using LL = long long;
using ULL = unsigned long long;
#define rep(i,n) for(int i=0; i<(n); i++)

int N, M;
char S[300001];
vector<int> E[300000];

int Nx[300001];


struct SplayTreeByIdx {
    struct S { int i; };
    static S op(S l, S r) { return {}; }
    static S rev(S p) { return {}; }
    static S e() { return { -1 }; }
    struct F {  };
    static S mapping(F f, S x) { return x; }
    static F composition(F f, F x) { return x; }
    static F id() { return {}; }
    struct Node {
        Node* l = 0, * r = 0, * p = 0;
        S a = e();
        S prod = e();
        F f = id();
        bool propagated = true;
        int z = 0;
        int sumz = 0;
        int rev = 0;
    };
    Node* NIL = nullptr;
    Node* R;
    void prepareDown(Node* c) {
        if (!c->propagated) {
            if (c->l != NIL) {
                c->l->prod = mapping(c->f, c->l->prod);
                c->l->f = composition(c->f, c->l->f);
                c->l->propagated = false;
            }
            if (c->r != NIL) {
                c->r->prod = mapping(c->f, c->r->prod);
                c->r->f = composition(c->f, c->r->f);
                c->r->propagated = false;
            }
            c->a = mapping(c->f, c->a);
            c->f = id();
            c->propagated = true;
        }
        if (c->rev) {
            swap(c->l, c->r);
            if (c->l != NIL) {
                c->l->rev ^= 1;
                c->l->prod = rev(c->l->prod);
            }
            if (c->r != NIL) {
                c->r->rev ^= 1;
                c->r->prod = rev(c->r->prod);
            }
            c->rev = 0;
        }
    }
    void prepareUp(Node* c) {
        c->sumz = c->l->sumz + c->r->sumz + 1;
        c->prod = op(op(c->l->prod, c->a), c->r->prod);
    }
    SplayTreeByIdx() {
        if (!NIL) {
            NIL = new Node();
            NIL->l = NIL->r = NIL->p = NIL;
            R = NIL;
        }
    }
    Node*& parentchild(Node* p) {
        if (p->p == NIL) return R;
        if (p->p->l == p) return p->p->l;
        else return p->p->r;
    }
    void rotL(Node* c) {
        Node* p = c->p;
        parentchild(p) = c;
        c->p = p->p; p->p = c;
        if (c->l != NIL) c->l->p = p;
        p->r = c->l; c->l = p;
    }
    void rotR(Node* c) {
        Node* p = c->p;
        parentchild(p) = c;
        c->p = p->p; p->p = c;
        if (c->r != NIL) c->r->p = p;
        p->l = c->r; c->r = p;
    }
    void splay(Node* c) {
        while (c->p != NIL) {
            Node* p = c->p;
            Node* pp = p->p;
            if (p->l == c) {
                if (pp == NIL) { rotR(c); }
                else if (pp->l == p) { rotR(p); rotR(c); }
                else if (pp->r == p) { rotR(c); rotL(c); }
            }
            else {
                if (pp == NIL) { rotL(c); }
                else if (pp->r == p) { rotL(p); rotL(c); }
                else if (pp->l == p) { rotL(c); rotR(c); }
            }
            if (pp != NIL) prepareUp(pp);
            if (p != NIL) prepareUp(p);
        }
        prepareUp(c);
    }
    Node* kth_element(int k) {
        if (k >= R->sumz) return NIL;
        Node* c = R;
        while (true) {
            prepareDown(c);
            auto cl = c->l;
            if (cl->sumz == k) break;
            if (cl->sumz > k) { c = cl; continue; }
            k -= cl->sumz + 1;
            c = c->r;
        }
        prepareDown(c);
        splay(c);
        return c;
    }
    Node* insert_at(int k, S x) {
        Node* nx = new Node(*NIL);
        nx->z = nx->sumz = 1;
        nx->a = nx->prod = x;
        if (k == R->sumz) {
            nx->l = R;
            if (R != NIL) R->p = nx;
            R = nx;
            prepareUp(nx);
            return nx;
        }
        auto p = kth_element(k);
        nx->l = p->l;
        nx->r = p;
        R = nx;
        if (p->l != NIL) {
            prepareDown(p->l);
            p->l->p = nx;
        }
        p->p = nx;
        p->l = NIL;
        prepareUp(p);
        prepareUp(nx);
        return nx;
    }
    void erase_at(int k) {
        if (k >= R->sumz) return;
        auto toerase = NIL;
        if (k == 0) {
            kth_element(0);
            prepareDown(R);
            toerase = R;
            R = R->r;
            if (R != NIL) R->p = NIL;
        }
        else {
            kth_element(k - 1);
            prepareDown(R);
            auto c = R->r;
            prepareDown(c);
            while (c->l != NIL) {
                c = c->l;
                prepareDown(c);
            }
            auto p = c->p;
            toerase = c;
            parentchild(c) = c->r;
            if (c->r != NIL) c->r->p = p;
            splay(p);
        }
    }
    Node* between(int l, int r) {
        if (l >= r) return NIL;
        if (l == 0 && r == R->sumz) return R;
        if (l == 0) return kth_element(r)->l;
        if (r == R->sumz) return kth_element(l - 1)->r;
        auto lp = kth_element(l - 1);
        auto rp = kth_element(r);
        while (rp->l != lp) {
            auto p = lp->p;
            prepareDown(p);
            prepareDown(lp);
            if (p->l == lp) rotR(lp);
            else rotL(lp);
            prepareUp(p);
            prepareUp(lp);
        }
        return lp->r;
    }
    void reverse(int l, int r) {
        if (l >= r) return;
        auto c = between(l, r);
        c->rev ^= 1;
        prepareDown(c);
        splay(c);
    }
    void apply(int l, int r, F f) {
        if (l >= r) return;
        auto c = between(l, r);
        c->prod = mapping(f, c->prod);
        c->f = composition(f, c->f);
        c->propagated = false;
        prepareDown(c);
        splay(c);
    }
    S prod(int l, int r) {
        if (l >= r) return e();
        return between(l, r)->prod;
    }

    vector<Node*> A;

    int index(int i){
        splay(A[i]);
        return A[i]->l->sumz;
    }
	// a < b
	bool comp(int a, int b) {
		if (::S[a] != ::S[b]) return ::S[a] < ::S[b];
		return index(Nx[a]) < index(Nx[b]);
	}
    
	void init() {
        A.resize(N+1);
		Nx[N] = N;
        A[N] = insert_at(0, {N});
		for (int i = N - 1; i >= 0; i--) {
			pair<int, int> nx = { N * 2,N };
			for (int e : E[i]) nx = min(nx, make_pair(index(e), e));
			Nx[i] = nx.second;
			int l = 0, r = N-i+1;
			while (l + 1 < r) {
				int m = (l + r) / 2;
				if (comp(kth_element(m - 1)->a.i, i)) l = m;
				else r = m;
			}
            A[i] = insert_at(l, {i});
		}
	}
};

int main() {
	scanf("%d%d", &N, &M);
	rep(i, N) scanf(" %c", &S[i]); S[N] = 0;
	rep(i, N - 1) E[i].push_back(i + 1);
	rep(i, M) {
		int u, v; scanf("%d%d", &u, &v); u--; v--;
		if (u + 1 == v) continue;
		E[u].push_back(v);
	}

	SplayTreeByIdx G; G.init();

	int p = 0;
	while (p != N) {
		printf("%c", S[p]);
		p = Nx[p];
	}
	printf("\n");

	return 0;
}
accuracy: 1
time_ms: 2130
memory_kb: 43280
final_rank: 12

code_snippet: #include <bits/stdc++.h>

template <class T> using Vec = std::vector<T>;

using u64 = std::uint64_t;

u64 xorshift() {
    static u64 cur = 904;
    cur ^= cur << 9;
    cur ^= cur >> 7;
    return cur;
}

struct Node;
using Ptr = std::unique_ptr<Node>;
using Weak = Node*;

struct Node {
    char front;
    int link;
    int size;
    u64 priority;
    Ptr left, right;
    Weak parent;
    explicit Node(char f, int l) : front(f), link(l), size(1), priority(xorshift()), left(), right(), parent(nullptr) {}
};

int get_size(const Ptr& p) { return p ? p->size : 0; }

void reset(Ptr& p) {
    if (p->left) {
        p->left->parent = p.get();
    }
    if (p->right) {
        p->right->parent = p.get();
    }
    p->size = get_size(p->left) + 1 + get_size(p->right);
}

void rotate_right(Ptr& p) {
    Ptr q = std::move(p->left);
    q->parent = nullptr;
    p->left = std::move(q->right);
    reset(p);
    q->right = std::move(p);
    p = std::move(q);
    reset(p);
}

void rotate_left(Ptr& p) {
    Ptr q = std::move(p->right);
    q->parent = nullptr;
    p->right = std::move(q->left);
    reset(p);
    q->left = std::move(p);
    p = std::move(q);
    reset(p);
}

template <class F> struct RecLambda : private F {
    explicit RecLambda(F&& f) : F(std::forward<F>(f)) {}
    template <class... Args> decltype(auto) operator()(Args&&... args) const {
        return F::operator()(*this, std::forward<Args>(args)...);
    }
};

template <class F> decltype(auto) rec_lambda(F&& f) {
    using G = std::decay_t<F>;
    return RecLambda<G>(std::forward<G>(f));
}

int main() {
    int N, M;
    std::cin >> N >> M;
    Vec<char> C(N);
    for (auto& x : C) {
        std::cin >> x;
    }
    Vec<Vec<int>> to(N);
    while (M--) {
        int u, v;
        std::cin >> u >> v;
        to[u - 1].push_back(v - 1);
    }
    Ptr root;
    Vec<Weak> ptr(N + 1, nullptr);
    const auto calc_pos = [&](const int i) {
        if (i == N) return -1;
        Weak p = ptr[i];
        int ret = get_size(p->left);
        while (p->parent) {
            Weak q = p->parent;
            if (p == q->right.get()) {
                ret += get_size(q->left) + 1;
            }
            p = q;
        }
        return ret;
    };
    root = std::make_unique<Node>(C[N - 1], N);
    ptr[N - 1] = root.get();
    for (int i = N - 2; i >= 0; --i) {
        int min_pos = calc_pos(i + 1);
        int link = i + 1;
        for (const auto j : to[i]) {
            const int tmp = calc_pos(j);
            if (min_pos > tmp) {
                min_pos = tmp;
                link = j;
            }
        }
        ptr[i] = rec_lambda([&](auto&& dfs, Ptr& p) -> Weak {
            if (!p) {
                p = std::make_unique<Node>(C[i], link);
                return p.get();
            }
            if (p->front < C[i] or (p->front == C[i] and calc_pos(p->link) < min_pos)) {
                const auto ret = dfs(p->right);
                reset(p);
                if (p->priority < p->right->priority) {
                    rotate_left(p);
                }
                return ret;
            } else {
                const auto ret = dfs(p->left);
                reset(p);
                if (p->priority < p->left->priority) {
                    rotate_right(p);
                }
                return ret;
            }
        })(root);
    }
    Weak p = ptr[0];
    while (p) {
        std::cout << p->front;
        p = ptr[p->link];
    }
    std::cout << '\n';
    return 0;
}
accuracy: 1
time_ms: 1230
memory_kb: 40796
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;

int main(){
  int N,M;
  cin >> N >> M;
  vector<char> c(N);
  for(int i=0;i<N;i++) cin >> c[i];
  vector<vector<int>> G(N);
  for(int i=0;i<M;i++){
    int u,v;
    cin >> u >> v;
    G[u-1].push_back(v-1);
  }
  map<int,string> dp;
  dp[N-1] = c[N-1];
  for(int i=N-2;i>=0;i--){
    string T = "";
    T += c[i];
    T += dp[i+1];
    dp[i] = T;
    if(G[i].size() == 0) continue;
    for(auto nv:G[i]){
      string S = "";
      S += c[i];
      S += dp[nv];
      dp[i] = min(dp[i],S);
    }
  }
  cout << dp[0] << endl;
}
accuracy: 0.3939393939393939
time_ms: 180
memory_kb: 55276
final_rank: 18

code_snippet: #include<bits/stdc++.h>
using namespace std;

int main(){
  int N,M;
  cin >> N >> M;
  vector<char> c(N);
  for(int i=0;i<N;i++) cin >> c[i];
  vector<vector<int>> G(N);
  for(int i=0;i<M;i++){
    int u,v;
    cin >> u >> v;
    G[u-1].push_back(v-1);
  }
  map<int,string> dp;
  dp[N-1] = c[N-1];
  for(int i=N-2;i>=0;i--){
    string T = "";
    T += c[i];
    T += dp[i+1];
    dp[i] = T;
    for(auto nv:G[i]){
      string S = "";
      S += c[i];
      S += dp[nv];
      dp[i] = min(dp[i],S);
    }
  }
  cout << dp[0] << endl;
}
accuracy: 0.3939393939393939
time_ms: 170
memory_kb: 55240
final_rank: 17

code_snippet: #include<bits/stdc++.h>
using namespace std;

int main(){
  int N,M;
  cin >> N >> M;
  vector<char> c(N);
  for(int i=0;i<N;i++) cin >> c[i];
  vector<vector<int>> G(N);
  for(int i=0;i<M;i++){
    int u,v;
    cin >> u >> v;
    G[u-1].push_back(v-1);
  }
  vector<string> dp(N,"");
  dp[N-1] += c[N-1];
  for(int i=N-2;i>=0;i--){
    dp[i] += c[i];
    dp[i] += dp[i+1];
    for(auto nv:G[i]){
      string S = "";
      S += c[i];
      S += dp[nv];
      dp[i] = min(dp[i],S);
    }
  }
  cout << dp[0] << endl;
}
accuracy: 0.3939393939393939
time_ms: 110
memory_kb: 50452
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;
const int LOG = 20;
const long long MOD = 1000000007;
const long long BASE = 1000000;
int main(){
  int N, M;
  cin >> N >> M;
  vector<char> c(N);
  for (int i = 0; i < N; i++){
    cin >> c[i];
  }
  vector<vector<int>> E(N);
  for (int i = 0; i < M; i++){
    int u, v;
    cin >> u >> v;
    u--;
    v--;
    if (v - u > 1){
      E[u].push_back(v);
    }
  }
  vector<vector<int>> p(LOG, vector<int>(N, -1));
  vector<vector<long long>> hash(LOG, vector<long long>(N, 0));
  for (int i = 0; i < N; i++){
    hash[0][i] = c[i];
  }
  for (int i = N - 2; i >= 0; i--){
    int nxt = i + 1;
    for (int v : E[i]){
      int a = v, b = nxt;
      for (int j = LOG - 1; j >= 0; j--){
        if (p[j][a] != -1 && p[j][b] != -1){
          if (hash[j][a] == hash[j][b]){
            a = p[j][a];
            b = p[j][b];
          }
        }
      }
      if (c[a] < c[b] || c[a] == c[b] && a == N - 1){
        nxt = v;
      }
    }
    p[0][i] = nxt;
    long long c = BASE;
    for (int j = 0; j < LOG - 1; j++){
      if (p[j][i] != -1){
        p[j + 1][i] = p[j][p[j][i]];
        hash[j + 1][i] = (hash[j][i] + hash[j][p[j][i]] * c) % MOD;
      }
      c = c * c % MOD;
    }
  }
  string ans;
  for (int v = 0; v != -1; v = p[0][v]){
    ans += c[v];
  }
  cout << ans << endl;
}
accuracy: 1
time_ms: 270
memory_kb: 92400
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
const int LOG = 19;
const long long MOD = 1000000007;
const long long BASE = 1000000;
int main(){
  int N, M;
  cin >> N >> M;
  vector<char> c(N);
  for (int i = 0; i < N; i++){
    cin >> c[i];
  }
  vector<vector<int>> E(N);
  for (int i = 0; i < M; i++){
    int u, v;
    cin >> u >> v;
    u--;
    v--;
    E[u].push_back(v);
  }
  vector<vector<int>> p(LOG, vector<int>(N, -1));
  vector<vector<long long>> hash(LOG, vector<long long>(N, 0));
  for (int i = 0; i < N; i++){
    hash[0][i] = c[i];
  }
  for (int i = N - 2; i >= 0; i--){
    int nxt = i + 1;
    for (int v : E[i]){
      if (c[v] < c[nxt]){
        nxt = v;
      } else if (c[v] == c[nxt]){
        int a = v, b = nxt;
        for (int j = LOG - 1; j >= 0; j--){
          if (p[j][a] != -1 && p[j][b] != -1){
            if (hash[j][a] == hash[j][b]){
              a = p[j][a];
              b = p[j][b];
            }
          }
        }
        if (c[a] < c[b] || c[a] == c[b] && a == N - 1){
          nxt = v;
        }
      }
    }
    p[0][i] = nxt;
    long long c = BASE;
    for (int j = 0; j < LOG - 1; j++){
      if (p[j][i] != -1){
        p[j + 1][i] = p[j][p[j][i]];
        hash[j + 1][i] = (hash[j][i] + hash[j][p[j][i]] * c) % MOD;
      }
      c = c * c % MOD;
    }
  }
  string ans;
  for (int v = 0; v != -1; v = p[0][v]){
    ans += c[v];
  }
  cout << ans << endl;
}
accuracy: 1
time_ms: 270
memory_kb: 88960
final_rank: 1

code_snippet: #define READ_FROM_FILE 0

#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <regex>


int main() {
#if READ_FROM_FILE
    std::string filename = "/home/ichino/data/workspace/AizuOnlineJudgeCpp/test1.txt";
    std::ifstream ifs(filename);
#endif
    int n = - 1;
    int m = - 1;
    std::string buf;
    std::string c_str;
    std::istringstream ss;
    std::vector<std::vector<int> > airline_vec;
    std::vector<std::string> s_vec;


#if READ_FROM_FILE
    std::getline(ifs, buf);
    ss = std::istringstream(buf);
    ss >> n >> m;

    std::getline(ifs, c_str);

    airline_vec.resize(n);

    for(int k = 0; k < m; k++){
        int i = - 1;
        int j = - 1;

        std::getline(ifs, buf);
        ss = std::istringstream(buf);
        ss >> i >> j;

        airline_vec[i - 1].push_back(j - 1);
    }
#else
    std::getline(std::cin, buf);
    ss = std::istringstream(buf);
    ss >> n >> m;

    std::getline(std::cin, c_str);

    airline_vec.resize(n);

    for(int k = 0; k < m; k++){
        int i = - 1;
        int j = - 1;

        std::getline(std::cin, buf);
        ss = std::istringstream(buf);
        ss >> i >> j;

        airline_vec[i - 1].push_back(j - 1);
    }
#endif
    c_str = std::regex_replace(c_str, std::regex(" "), "");
    s_vec.resize(n);

    s_vec.back().push_back(c_str[n - 1]);

    for(int i = n - 2; i >= 0; i--) {
        std::string tmp_str(1, c_str[i]);

        s_vec[i] = tmp_str + s_vec[i + 1];

        for(int j = 0; j < airline_vec[i].size(); j++) {
            std::string str_j = tmp_str + s_vec[airline_vec[i][j]];

            if(s_vec[i] > str_j) {
                s_vec[i] = str_j;
            }
        }
    }

    std::cout << s_vec[0] << std::endl;

    return 0;
}
accuracy: 0.3939393939393939
time_ms: 170
memory_kb: 50760
final_rank: 16

code_snippet: #include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
#include <set>
#include <iomanip>
#include <queue>
#include <string>
#include <map>
#include <fstream>
#include <cassert>
#include <stack>
#include <climits>
#include <array>
#include <unordered_set>
#include <unordered_map>
#include <memory>
#include <functional>
#include <cfloat>
#include <numeric>
#include <random>
template<typename T>
class Treap {
public:
	Treap(std::function<bool(const T&, const T&)> comparator) : comparator(comparator), rand{ 0 } {};
	struct Node {
		int prioriy;
		int size;
		T value;
		Node* parent, * left, * right;
	};
	Node* const insert(const T& new_value) {
		root = insert_inner(root, new_value);
		return temp;
	}
	int calc_rank(Node* const node) const {
		return size_of(node->left) + calc_rank(node->parent, node);
	}
private:
	std::function<bool(const T&, const T&)> comparator;
	Node* root{ nullptr }, *temp{ nullptr };
	std::mt19937 rand;
	std::uniform_int_distribution<int> dist;
	Node* insert_inner(Node* current, const T& value) {
		if (current) {
			if (comparator(value, current->value)) {
				current->left = insert_inner(current->left, value);
				current->left->parent = current;
				++current->size;
				if (current->left->prioriy > current->prioriy) {
					return rotate_right(current);
				}
				else {
					return current;
				}
			}
			else {
				current->right = insert_inner(current->right, value);
				current->right->parent = current;
				++current->size;
				if (current->right->prioriy > current->prioriy) {
					return rotate_left(current);
				}
				else {
					return current;
				}
			}
		}
		else {
			return temp = new Node{ dist(rand), 1, value, nullptr, nullptr, nullptr };
		}
	}
	Node* rotate_left(Node* root) {
		const auto right = root->right;
		root->right = right->left;
		if (root->right) root->right->parent = root;
		right->left = root;
		right->parent = root->parent;
		root->parent = right;
		right->size = root->size;
		root->size = size_of(root->left) + size_of(root->right) + 1;
		return right;
	}
	Node* rotate_right(Node* root) {
		const auto left = root->left;
		root->left = left->right;
		if (root->left) root->left->parent = root;
		left->right = root;
		left->parent = root->parent;
		root->parent = left;
		left->size = root->size;
		root->size = size_of(root->left) + size_of(root->right) + 1;
		return left;
	}
	int calc_rank(Node* const current, Node* const target) const {
		if (current) {
			if (current->right == target) return calc_rank(current->parent, current) + size_of(current->left) + 1;
			else return calc_rank(current->parent, current);
		}
		else return 0;
		
	}
	int size_of(Node* const node) const {
		return node ? node->size : 0;
	}
};



int main() {
	int n, m; std::cin >> n >> m;
	std::vector<char> country(n);
	for (auto& c : country) std::cin >> c;
	country.push_back('\0');
	std::vector<std::vector<int>> next(n + 1);
	for (auto i = 0; i < m; ++i) {
		int u, v; std::cin >> u >> v; --u; --v;
		next[u].push_back(v);
	}
	for (auto i = 0; i < n; ++i) {
		next[i].push_back(i + 1);
	}
	std::vector<int> next_min(n + 1, -1);
	std::vector<Treap<int>::Node*> node(n + 1);
	Treap<int>* treap{ nullptr };
	const auto comparator = [&treap, &country, &next_min, &node](const int i, const int j) {
		if (i == j) return false;
		if (country[i] != country[j]) return country[i] < country[j];
		if (next_min[i] == next_min[j]) return false;
		return treap->calc_rank(node[next_min[i]]) < treap->calc_rank(node[next_min[j]]);
	};
	treap = new Treap<int>(comparator);
	node[n] = treap->insert(n);
	for (auto i = n - 1; i >= 0; --i) {
		std::sort(next[i].begin(), next[i].end(), comparator);
		next_min[i] = *std::min_element(next[i].begin(), next[i].end(), comparator);
		node[i] = treap->insert(i);
	}
	for (auto i = 0; i != n; i = next_min[i]) {
		std::cout << country[i];
	}
	std::cout << std::endl;
}
accuracy: 1
time_ms: 1590
memory_kb: 37904
final_rank: 7

code_snippet: // verification-helper: PROBLEM http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0438

#include<bits/stdc++.h>
using namespace std;

#define call_from_test
#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;
#endif

//BEGIN CUT HERE
template<typename T=int>
vector<T> read(size_t n){
  vector<T> ts(n);
  for(size_t i=0;i<n;i++) cin>>ts[i];
  return ts;
}
//END CUT HERE
#ifndef call_from_test
signed main(){
  return 0;
}
#endif

#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
template<typename Impl, typename Data, typename Node, size_t LIM>
struct RBST{
  using u32 = uint32_t;
  u32 xor128(){
    static u32 x = 123456789;
    static u32 y = 362436069;
    static u32 z = 521288629;
    static u32 w = 88675123;

    u32 t = x ^ (x << 11);
    x = y; y = z; z = w;
    return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
  }

  alignas(Node) static inline char pool[sizeof(Node)*LIM];
  static inline Node* ptr = (Node*)pool;
  static inline size_t size;

  template<typename... Args>
  inline Node* create(Args&&... args){
    return new (ptr+size++) Node(std::forward<Args>(args)...);
  }

  inline size_t count(const Node *t){return Data::count(t);}

  inline Node* touch(Node *t){
    return static_cast<Impl*>(this)->touch(t);
  }

  inline void toggle(Node *t){
    return static_cast<Impl*>(this)->toggle(t);
  }

  inline Node* pushup(Node *t){
    return static_cast<Impl*>(this)->pushup(t);
  }

  Node* toggle(Node *a,size_t l,size_t r){
    auto s=split(a,l);
    auto t=split(s.second,r-l);
    auto u=touch(t.first);
    toggle(u);
    return merge(s.first,merge(u,t.second));
  }

  Node* merge(Node* a,Node* b){
    if(a==nullptr) return b;
    if(b==nullptr) return a;
    if(xor128()%(count(a)+count(b))<count(a)){
      a=touch(a);
      a->r=merge(a->r,b);
      a->r->p=a;
      return pushup(a);
    }
    b=touch(b);
    b->l=merge(a,b->l);
    b->l->p=b;
    return pushup(b);
  }

  pair<Node*, Node*> split(Node* a,size_t k){
    if(a==nullptr) return make_pair(a,a);
    a=touch(a);
    if(k<=count(a->l)){
      if(a->l) a->l->p=nullptr;
      auto s=split(a->l,k);
      a->l=s.second;
      if(a->l) a->l->p=a;
      return make_pair(s.first,pushup(a));
    }
    if(a->r) a->r->p=nullptr;
    auto s=split(a->r,k-(count(a->l)+1));
    a->r=s.first;
    if(a->r) a->r->p=a;
    return make_pair(pushup(a),s.second);
  }

  Node* insert(Node *a,size_t k,Node v){
    Node* b=create(v);
    auto s=split(a,k);
    return merge(merge(s.first,b),s.second);
  }

  Node* erase(Node *a,size_t k){
    assert(k<count(a));
    auto s=split(a,k);
    auto t=split(s.second,1);
    return merge(s.first,t.second);
  }

  Node* find_by_order(Node *a,size_t k){
    assert(k<count(a));
    a=touch(a);
    size_t num=count(a->l);
    if(k<num) return find_by_order(a->l,k);
    if(k>num) return find_by_order(a->r,k-(num+1));
    return a;
  }

  inline bool is_right(Node* a){
    return a->p and a->p->r==a;
  }

  size_t order_of_key(Node* a){
    size_t res=count(a->l);
    while(a){
      if(is_right(a)) res+=count(a->p->l)+1;
      a=a->p;
    }
    return res;
  }

  Node* build(size_t l,size_t r,const vector<Node> &vs){
    if(l+1==r) return create(vs[l]);
    size_t m=(l+r)>>1;
    return merge(build(l,m,vs),build(m,r,vs));
  }

  Node* build(const vector<Node> &vs){
    return build(0,vs.size(),vs);
  }

  template<typename T>
  Node* set_val(Node *a,size_t k,T val){
    assert(k<count(a));
    a=touch(a);
    size_t num=count(a->l);
    if(k<num) a->l=set_val(a->l,k,val);
    if(k>num) a->r=set_val(a->r,k-(num+1),val);
    if(k==num) a->val=val;
    return pushup(a);
  }

  Node* get_val(Node *a,size_t k){
    assert(k<count(a));
    a=touch(a);
    size_t num=count(a->l);
    if(k<num) return get_val(a->l,k);
    if(k>num) return get_val(a->r,k-(num+1));
    return a;
  }

  template<typename E>
  Node* update(Node *a,size_t l,size_t r,E v){
    auto s=split(a,l);
    auto t=split(s.second,r-l);
    auto u=touch(t.first);
    propagate(u,v);
    return merge(s.first,merge(u,t.second));
  }

  decltype(auto) query(Node *&a,size_t l,size_t r){
    auto s=split(a,l);
    auto t=split(s.second,r-l);
    auto u=t.first;
    auto res=static_cast<Impl*>(this)->query(u);
    a=merge(s.first,merge(u,t.second));
    return res;
  }
};
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif

#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
template<typename T>
struct Array{
  struct Node{
    Node *l,*r,*p;
    size_t cnt;
    bool rev;
    T val;
    Node(T val):
      cnt(1),rev(0),val(val){l=r=p=nullptr;}
  };

  static inline size_t count(const Node *t){
    return t?t->cnt:0;
  }

  inline void toggle(Node *t){
    swap(t->l,t->r);
    t->rev^=1;
  }

  inline bool dirty(Node *t){
    return t->rev;
  }

  inline Node* eval(Node* t){
    if(t->rev){
      if(t->l) toggle(t->l);
      if(t->r) toggle(t->r);
      t->rev=false;
    }
    return t;
  }

  inline Node* pushup(Node *t){
    t->cnt=count(t->l)+1+count(t->r);
    return t;
  }

  inline T reflect(Node *t){
    assert(t);
    return t->val;
  }

  void dump(typename vector<Node>::iterator it,Node* const t,bool rev){
    if(!count(t)) return;

    Node *l=t->l,*r=t->r;
    if(rev) swap(l,r);
    rev^=t->rev;

    dump(it,l,rev);
    *(it+count(l))=Node(t->val);
    dump(it+count(l)+1,r,rev);
  }

  vector<Node> dump(Node* t){
    assert(t!=nullptr);
    vector<Node> vs(count(t),*t);
    dump(vs.begin(),t,false);
    return vs;
  }
};
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif

#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;

#define call_from_test
#include "../rbst.cpp"
#undef call_from_test

#endif
//BEGIN CUT HERE
template<typename Data, size_t LIM>
struct Basic : RBST<Basic<Data, LIM>, Data, typename Data::Node, LIM>{
  using super = RBST<Basic, Data, typename Data::Node, LIM>;
  using Node = typename Data::Node;

  Data data;

  template<class... Args>
  Basic(Args... args):data(forward<Args>(args)...){}

  inline Node* touch(Node *t){return data.eval(t);}

  using super::toggle;
  inline void toggle(Node *t){return data.toggle(t);}
  inline Node* pushup(Node *t){return data.pushup(t);}

  inline decltype(auto) get_val(Node *a,size_t k){
    return data.reflect(super::get_val(a,k));
  }

  using super::query;
  inline decltype(auto) query(Node *a){
    return data.reflect(a);
  }
};
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif

#undef call_from_test

struct T;
using Node = Array<T>::Node;

struct T{
  Node* nxt;
  char c;
  T():nxt(nullptr){}
  T(Node* nxt,char c):nxt(nxt),c(c){}
};

signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);

  int n,m;
  cin>>n>>m;
  auto cs=read<char>(n);

  vector<vector<int>> G(n);
  for(int i=0;i+1<n;i++)
    G[i].emplace_back(i+1);

  for(int i=0;i<m;i++){
    int u,v;
    cin>>u>>v;
    u--;v--;
    G[u].emplace_back(v);
  }

  const size_t LIM = 1e6;
  using Data = Array<T>;
  Basic<Data, LIM> H;
  vector<Node*> ps(n,nullptr);
  ps[n-1]=H.create(Node(T(nullptr,cs[n-1])));
  auto R=ps[n-1];

  for(int i=n-2;i>=0;i--){
    auto nxt=ps[i+1];

    auto comp1=[&](Node* a,Node* b){
      return H.order_of_key(a)<H.order_of_key(b);
    };

    for(int j:G[i])
      if(comp1(ps[j],nxt)) nxt=ps[j];

    ps[i]=H.create(Node(T(nxt,cs[i])));

    auto comp2=[&](Node* a,Node* b){
      if(a->val.c!=b->val.c) return (a->val.c)<(b->val.c);
      if(a->val.nxt==b->val.nxt) return false;
      if(!a->val.nxt) return true;
      if(!b->val.nxt) return false;
      return comp1(a->val.nxt,b->val.nxt);
    };

    int l=-1,r=n-(i+1);
    // comp(ps[i], l) : false
    // comp(ps[i], r) : true
    while(l+1<r){
      int m=(l+r)>>1;
      auto p=H.find_by_order(R,m);
      if(comp2(ps[i],p)) r=m;
      else l=m;
    }
    auto s=H.split(R,r);
    R=H.merge(H.merge(s.first,ps[i]),s.second);
  }

  auto cur=ps[0];
  while(cur){
    cout<<(cur->val.c);
    cur=cur->val.nxt;
  }
  cout<<endl;
  return 0;
}
accuracy: 1
time_ms: 1870
memory_kb: 41780
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;
struct RollingHash {
  static const uint64_t mod = (1ull << 61ull) - 1;
  using uint128_t = __uint128_t;
  vector< uint64_t > hashed, power;
  const uint64_t base;
  static inline uint64_t add(uint64_t a, uint64_t b){
    if((a += b) >= mod) a -= mod;
    return a;
  }
  static inline uint64_t mul(uint64_t a, uint64_t b){
    uint128_t c = (uint128_t) a * b;
    return add(c >> 61, c & mod);
  }
  static inline uint64_t generate_base() {
    mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());
    uniform_int_distribution< uint64_t > rand(1, RollingHash::mod - 1);
    return rand(mt);
  }
  RollingHash() = default;
  RollingHash(const string &s, uint64_t base) : base(base) {
    size_t sz = s.size();
    hashed.assign(sz + 1, 0);
    power.assign(sz + 1, 0);
    power[0] = 1;
    for(int i = 0; i < sz; i++) {
      power[i + 1] = mul(power[i], base);
      hashed[i + 1] = add(mul(hashed[i], base), s[i]);
    }
  }
  template< typename T >
  RollingHash(const vector< T > &s, uint64_t base) : base(base) {
    size_t sz = s.size();
    hashed.assign(sz + 1, 0);
    power.assign(sz + 1, 0);
    power[0] = 1;
    for(int i = 0; i < sz; i++) {
      power[i + 1] = mul(power[i], base);
      hashed[i + 1] = add(mul(hashed[i], base), s[i]);
    }
  }
  uint64_t query(int l, int r) const {
    return add(hashed[r], mod - mul(hashed[l], power[r - l]));
  }
  uint64_t combine(uint64_t h1, uint64_t h2, size_t h2len) const {
    return add(mul(h1, power[h2len]), h2);
  }
  int lcp(const RollingHash &b, int l1, int r1, int l2, int r2) const {
    assert(base == b.base);
    int len = min(r1 - l1, r2 - l2);
    int low = 0, high = len + 1;
    while(high - low > 1) {
      int mid = (low + high) / 2;
      if(query(l1, l1 + mid) == b.query(l2, l2 + mid)) low = mid;
      else high = mid;
    }
    return low;
  }
};
#define ll long long
#define all(a)  (a).begin(),(a).end()
#define fi(g,n)  for(int i=g;i<n;i++)
#define fj(g,n)  for(int j=g;j<n;j++)
#define vc(a,z) vector<a> v(z,0)
int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n,m,a,b,pos,aa,bb;
    cin>>n>>m;
    vector<char> c(n);
    fi(0,n){
        cin>>c[i];
    }
    RollingHash rh(c,RollingHash::generate_base());
    vector<vector<int>> load(n+1);
    fi(0,m){
        cin>>a>>b;
        --a;
        --b;
        load[a].emplace_back(b);
    }
    vector<vector<uint64_t>> hash(n+1,vector<uint64_t>(31));
    vector<vector<int>> next(n+1,vector<int>(31,-1));
    vector<int> siz(n+1);
    for(int i=n-2;i>=0;--i){
        pos=i+1;
        for(auto p:load[i]){
            if(c[pos]==c[p]){
                a=pos;
                b=p;
                if(siz[a]>siz[b]) swap(a,b);
                aa=a;
                bb=b;
                for(int j=25;j>=0;--j){
                    if(next[a][j]!=-1){
                        if(hash[a][j]==hash[b][j]){
                            a=next[a][j];
                            b=next[b][j];
                        }
                    }
                }
                if(next[a][0]==-1) pos=aa;
                else if(c[next[a][0]]<c[next[b][0]]) pos=aa;
                else pos=bb;
            }else if(c[pos]>c[p]){
                pos=p;
            }
        }
        next[i][0]=pos;
        hash[i][0]=rh.query(pos,pos+1);
        siz[i]=siz[pos]+1;
        fj(0,25){
            if(next[i][j]!=-1){
                next[i][j+1]=next[next[i][j]][j];
                hash[i][j+1]=rh.combine(hash[i][j],hash[next[i][j]][j],(1<<j));
            }else{
                next[i][j+1]=-1;
            }
        }
    }
    string ans;
    pos=0;
    while(pos!=-1){
        ans.push_back(c[pos]);
        pos=next[pos][0];
    }
    cout<<ans<<'\n';
    return 0;
}
accuracy: 1
time_ms: 480
memory_kb: 157292
final_rank: 8

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 300005
#define NUM1 1000000007
#define NUM2 99999883
#define POW_MAX 19

struct Info{
	ull hash_1,hash_2;
};

int N,M;
int POW2[POW_MAX+1];
int NEXT[SIZE][POW_MAX];
char word[SIZE];
ull POW[SIZE][2],HASH[SIZE][POW_MAX][2],LENGTH[SIZE][POW_MAX];
vector<int> G[SIZE];

void calc_POW(){

	POW[0][0] = 1;
	POW[0][1] = 1;

	for(int i = 1; i <= N; i++){

		POW[i][0] = POW[i-1][0]*NUM1;
		POW[i][1] = POW[i-1][1]*NUM2;
	}
}

bool is_smaller(int a,int b){

	if(word[a] != word[b]){
		return word[a] < word[b];
	}

	int tmp_a = a,tmp_b = b;

	//文字列が一致する最大長を求める
	while(true){

		int left = 0,right = POW_MAX-1,mid = (left+right)/2;
		int tmp_pow = -1;

		while(left <= right){

			int a_next = NEXT[tmp_a][mid];
			int b_next = NEXT[tmp_b][mid];

			if(a_next == -1 || b_next == -1){

				right = mid-1;

			}else{

				if(HASH[tmp_a][mid][0] == HASH[tmp_b][mid][0] &&
						HASH[tmp_a][mid][1] == HASH[tmp_b][mid][1]){

					tmp_pow = mid;
					left = mid+1;

				}else{

					right = mid-1;
				}
			}
			mid = (left+right)/2;
		}
		if(tmp_pow == -1)break;

		tmp_a = NEXT[tmp_a][tmp_pow];
		tmp_b = NEXT[tmp_b][tmp_pow];
	}
	tmp_a = NEXT[tmp_a][0];
	tmp_b = NEXT[tmp_b][0];
	if((tmp_a == -1 && tmp_b != -1)|| (tmp_a != -1 && tmp_b != -1 && word[tmp_a] < word[tmp_b])){

		return true;

	}else{

		return false;
	}
}

int main(){

	POW2[0] = 1;
	for(int i = 1; i <= POW_MAX; i++){

		POW2[i] = POW2[i-1]*2;
	}

	scanf("%d %d",&N,&M);

	char buf[2];

	for(int i = 0; i < N; i++){

		scanf("%s",buf);
		word[i] = buf[0];
	}

	int from,to;

	for(int i = 0; i < M; i++){
		scanf("%d %d",&from,&to);
		from--;
		to--;
		G[from].push_back(to);
	}

	calc_POW();

	for(int i = 0; i < N; i++){
		for(int k = 0; k < POW_MAX; k++){

			NEXT[i][k] = -1;//国i始点の、POW[k]文字後のインデックス
		}
	}

	HASH[N-1][0][0] = 0;
	HASH[N-1][0][1] = 0;
	LENGTH[N-1][0] = 1;

	for(int i = N-2; i >= 0; i--){
		int tmp_next = i+1;
		for(int k = 0; k < G[i].size(); k++){
			int work_next = G[i][k];

			if(is_smaller(work_next,tmp_next)){

				tmp_next = work_next;
			}
		}
		NEXT[i][0] = tmp_next;
		HASH[i][0][0] = word[tmp_next];
		HASH[i][0][1] = word[tmp_next];
		LENGTH[i][0] = 1;

		for(int k = 1; k < POW_MAX; k++){
			if(NEXT[i][k-1] == -1)break;
			NEXT[i][k] = NEXT[NEXT[i][k-1]][k-1];
			for(int a = 0; a <= 1; a++){
				HASH[i][k][a] = HASH[i][k-1][a]*POW[LENGTH[NEXT[i][k-1]][k-1]][a]+HASH[NEXT[i][k-1]][k-1][a];
			}
			LENGTH[i][k] = LENGTH[i][k-1]+LENGTH[NEXT[i][k-1]][k-1];
		}
	}

	int tmp_node = 0;
	while(true){
		printf("%c",word[tmp_node]);
		tmp_node = NEXT[tmp_node][0];
		if(tmp_node == -1)break;
	}
	printf("\n");

	return 0;
}
accuracy: 1
time_ms: 390
memory_kb: 180296
final_rank: 9