Problem:
Game Strategy
You have found an old board game in the club room of your programming club. It looks interesting, so you decide to play it.
The game consists of
M
events, and you have to capture event
i
at time
t
i
. However, your strength must be at least
s
i
at that time. Otherwise, the game is over. At the beginning of the game (time 0), your strength is 0, but you can increase it by buying items. Your money is also 0 at the beginning of the game, but it increases by 1 per unit of time.
There are
N
items on the board, numbered 1 to
N
. Item
i
costs
v
i
, and buying it increases your strength by
h
i
. You can buy as many items as you want at any time, as long as you have enough money. However, you must choose the item with the lowest number among the remaining items. Each item will be disappeared after it is bought.
You can also buy multiple items in a row at the same time, and get a bonus equal to the sum of the differences in
h
i
of the adjacent items. For example, if you buy items 1, 2, 3 at the same time, your strength will increase by |
h
1
-
h
2
| + |
h
2
-
h
3
| in addition to
h
1
+
h
2
+
h
3
.
You want to maximize the amount of money you have, after capturing all the events.
Make a program to output the maximum amount of money you have after capturing all the events, using the information of items and events given in input.
Input
The input is given in the following format.
N
M
v
1
h
1
v
2
h
2
:
v
N
h
N
t
1
s
1
t
2
s
2
:
t
M
s
M
In the first line, the number of items
N
(1 ≤
N
≤ 3000) and the number of events
M
(1 ≤
M
≤ 1000) are given. In the following
N
lines, the cost
v
i
and the increase in strength
h
i
(1 ≤
v
i
,
h
i
≤ 100000) of the item
i
are given. In the following
M
lines, the time
t
i
and the condition
s
i
(1 ≤
t
i
,
s
i
≤ 100000) of the event
i
are given. However, if
i
<
j
, then
t
i
<
t
j
. All inputs are given as integers.
Output
Output the maximum amount of money you have in a line. However, if it is not possible to capture the events, output -1.
Sample Input 1
5 4
3 3
2 1
1 5
4 2
2 6
4 1
8 2
10 4
12 17
Sample Output 1
2
Sample Input 2
5 4
3 3
2 1
1 5
4 2
2 6
4 1
8 2
10 4
12 30
Sample Output 2
-1

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ld=long double;
#define fi first;
#define se second;
#define i128 __int128_t
#define all(x) x.begin(),x.end()
#define rep(i,n) for(int i=0;i<(int)(n);++i)
#define si(a) (long)(a.size())
template<typename T>bool chmin(T&a,T b){return b<a?(a=b,1):0;}
template<typename T>bool chmax(T&a,T b){return b>a?(a=b,1):0;}
const int INF=1e9+100;
const long INFL=3e18+100;
struct _ {
   _() { cin.tie(0)->sync_with_stdio(0), cout.tie(0); }
} __;

int main(){
    int N,M;
    cin>>N>>M;
    vector<int> v(N),h(N);
    rep(i,N)cin>>v[i]>>h[i];

    vector<int> V(N+1,0),H(N+1,0);
    rep(i,N) V[i+1]=V[i]+v[i];
    rep(i,N) H[i+1]=H[i]+h[i];

    vector<int> HS(N+1,0);
    rep(i,N) HS[i+1]=HS[i]+h[i]+(i!=0?abs(h[i]-h[i-1]):0);

    vector<int> dp(N+1,-1e9);
    dp[0]=0;
    int mae=0;
    rep(_,M){
        int t,s;
        cin>>t>>s;
        vector<int> np(N+1,-1e9);
        
        int r=upper_bound(all(V), t)-V.begin();
        rep(i,N){
            if(dp[i]<0) continue;
            
            if(dp[i]+h[i]>=s){
                chmax(np[i+1], dp[i]+h[i]);
            }
            else {
                int l=lower_bound(all(HS), s-(dp[i]+h[i]-HS[i+1]))-HS.begin();
                chmax(l, i+2);
                chmax(np[l], dp[i]+h[i]+HS[l]-HS[i+1]);
            }
        }
        rep(i,N-1){
            chmax(np[i+2], np[i+1]+h[i+1]+abs(h[i+1]-h[i]));
        }

        rep(i,N+1){
            if(dp[i]>=s){
                chmax(np[i], dp[i]);
            }
        }

        for(int i=r;i<=N;i++) np[i]=-1e9;
        swap(dp, np);
        mae=t;
    }
    int ans=-1;
    rep(i,N+1) if(dp[i]>=0){
        ans=mae-V[i];
        break;
    }
    cout<<ans<<"\n";
}
accuracy: 1
time_ms: 10
memory_kb: 3472
final_rank: 3

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

#ifdef LOCAL
#include <debug.hpp>
#else
#define debug(...)
#endif

// ref: https://nyaannyaan.github.io/library/hashmap/hashmap.hpp.html
namespace HashMapImpl {
using u32 = uint32_t;
using u64 = uint64_t;

template <typename Key, typename Data>
struct HashMapBase;

template <typename Key, typename Data>
struct itrB {
    // [UPDATE] C++17 で非推奨になった std::iterator template から変更
    using iterator_category = bidirectional_iterator_tag;
    using value_type = Data;
    using difference_type = ptrdiff_t;
    using pointer = value_type*;
    using reference = value_type&;

    u32 i;
    HashMapBase<Key, Data>* p;

    explicit constexpr itrB() : i(0), p(nullptr) {}
    explicit constexpr itrB(u32 _i, HashMapBase<Key, Data>* _p) : i(_i), p(_p) {}
    explicit constexpr itrB(u32 _i, const HashMapBase<Key, Data>* _p) : i(_i), p(const_cast<HashMapBase<Key, Data>*>(_p)) {}
    friend void swap(itrB& l, itrB& r) { swap(l.i, r.i), swap(l.p, r.p); }
    friend bool operator==(const itrB& l, const itrB& r) { return l.i == r.i; }
    friend bool operator!=(const itrB& l, const itrB& r) { return l.i != r.i; }
    const reference operator*() const { return const_cast<const HashMapBase<Key, Data>*>(p)->data[i]; }
    reference operator*() { return p->data[i]; }
    pointer operator->() const { return &(p->data[i]); }

    itrB& operator++() {
        assert(i != p->cap && "itr::operator++()");
        do {
            i++;
            if (i == p->cap) break;
            if (p->occupied_flag[i] && !p->deleted_flag[i]) break;
        } while (true);
        return (*this);
    }
    itrB operator++(int) {
        itrB it(*this);
        ++(*this);
        return it;
    }
    itrB& operator--() {
        do {
            i--;
            if (p->occupied_flag[i] && !p->deleted_flag[i]) break;
            assert(i != 0 && "itr::operator--()");
        } while (true);
        return (*this);
    }
    itrB operator--(int) {
        itrB it(*this);
        --(*this);
        return it;
    }
};

template <typename Key, typename Data>
struct HashMapBase {
    using u32 = uint32_t;
    using u64 = uint64_t;
    using iterator = itrB<Key, Data>;
    using itr = iterator;

   protected:
    template <typename K>
    inline u64 randomized(const K& key) const {
        return u64(key) ^ r;
    }
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<is_integral<K>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        return (randomized(key) * 11995408973635179863ULL) >> shift;
    }
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<is_integral<decltype(K::first)>::value, nullptr_t> = nullptr, enable_if_t<is_integral<decltype(K::second)>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        u64 a = randomized(key.first), b = randomized(key.second);
        a *= 11995408973635179863ULL;
        b *= 10150724397891781847ULL;
        return (a + b) >> shift;
    }
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<is_integral<typename K::value_type>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        static constexpr u64 mod = (1LL << 61) - 1;
        static constexpr u64 base = 950699498548472943ULL;
        u64 res = 0;
        for (auto& elem : key) {
            __uint128_t x = __uint128_t(res) * base + (randomized(elem) & mod);
            res = (x & mod) + (x >> 61);
        }
        __uint128_t x = __uint128_t(res) * base;
        res = (x & mod) + (x >> 61);
        if (res >= mod) res -= mod;
        return res >> (shift - 3);
    }
    // [ADD] 数値を要素とする 2 次元コンテナ用のハッシュ関数を追加
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<!is_integral<typename K::value_type>::value, nullptr_t> = nullptr, enable_if_t<is_integral<typename K::value_type::value_type>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        static constexpr u64 mod = (1LL << 61) - 1;
        static constexpr u64 base = 950699498548472943ULL;
        u64 res = 0;
        for (auto& container : key) {
            for (auto& elem : container) {
                __uint128_t x = __uint128_t(res) * base + (randomized(elem) & mod);
                res = (x & mod) + (x >> 61);
            }
        }
        __uint128_t x = __uint128_t(res) * base;
        res = (x & mod) + (x >> 61);
        if (res >= mod) res -= mod;
        return res >> (shift - 3);
    }

    template <typename D = Data, enable_if_t<is_same<D, Key>::value, nullptr_t> = nullptr>
    inline u32 hash(const D& dat) const {
        return inner_hash(dat);
    }
    template <typename D = Data, enable_if_t<is_same<decltype(D::first), Key>::value, nullptr_t> = nullptr>
    inline u32 hash(const D& dat) const {
        return inner_hash(dat.first);
    }

    template <typename D = Data, enable_if_t<is_same<D, Key>::value, nullptr_t> = nullptr>
    inline Key data_to_key(const D& dat) const {
        return dat;
    }
    template <typename D = Data, enable_if_t<is_same<decltype(D::first), Key>::value, nullptr_t> = nullptr>
    inline Key data_to_key(const D& dat) const {
        return dat.first;
    }

    void reallocate(u32 ncap) {
        vector<Data> ndata(ncap);
        vector<bool> nf(ncap);
        shift = 64 - __lg(ncap);
        for (u32 i = 0; i < cap; i++) {
            if (occupied_flag[i] && !deleted_flag[i]) {
                u32 h = hash(data[i]);
                while (nf[h]) h = (h + 1) & (ncap - 1);
                ndata[h] = move(data[i]);
                nf[h] = true;
            }
        }
        data.swap(ndata);
        occupied_flag.swap(nf);
        cap = ncap;
        occupied = s;
        deleted_flag.resize(cap);
        fill(std::begin(deleted_flag), std::end(deleted_flag), false);
    }

    inline bool extend_rate(u32 x) const { return x * 2 >= cap; }

    inline bool shrink_rate(u32 x) const { return HASHMAP_DEFAULT_SIZE < cap && x * 10 <= cap; }

    inline void extend() { reallocate(cap << 1); }

    inline void shrink() { reallocate(cap >> 1); }

   public:
    u32 cap, s, occupied;
    vector<Data> data;
    vector<bool> occupied_flag, deleted_flag;
    u32 shift;
    static u64 r;
    static constexpr uint32_t HASHMAP_DEFAULT_SIZE = 4;

    explicit HashMapBase() : cap(HASHMAP_DEFAULT_SIZE), s(0), occupied(0), data(cap), occupied_flag(cap), deleted_flag(cap), shift(64 - __lg(cap)) {}

    itr begin() const {
        u32 h = 0;
        while (h != cap) {
            if (occupied_flag[h] && !deleted_flag[h]) break;
            h++;
        }
        return itr(h, this);
    }
    itr end() const { return itr(this->cap, this); }

    friend itr begin(const HashMapBase& h) { return h.begin(); }
    friend itr end(const HashMapBase& h) { return h.end(); }

    itr find(const Key& key) const {
        u32 h = inner_hash(key);
        while (true) {
            if (occupied_flag[h] == false) return this->end();
            if (data_to_key(data[h]) == key) {
                if (deleted_flag[h] == true) return this->end();
                return itr(h, this);
            }
            h = (h + 1) & (cap - 1);
        }
    }

    bool contain(const Key& key) const { return find(key) != this->end(); }

    itr insert(const Data& d) {
        u32 h = hash(d);
        while (true) {
            if (occupied_flag[h] == false) {
                if (extend_rate(occupied + 1)) {
                    extend();
                    h = hash(d);
                    continue;
                }
                data[h] = d;
                occupied_flag[h] = true;
                ++occupied, ++s;
                return itr(h, this);
            }
            if (data_to_key(data[h]) == data_to_key(d)) {
                if (deleted_flag[h] == true) {
                    data[h] = d;
                    deleted_flag[h] = false;
                    ++s;
                }
                return itr(h, this);
            }
            h = (h + 1) & (cap - 1);
        }
    }

    // tips for speed up :
    // if return value is unnecessary, make argument_2 false.
    itr erase(itr it, bool get_next = true) {
        if (it == this->end()) return this->end();
        s--;
        if (!get_next) {
            this->deleted_flag[it.i] = true;
            if (shrink_rate(s)) shrink();
            return this->end();
        }
        itr nxt = it;
        nxt++;
        this->deleted_flag[it.i] = true;
        if (shrink_rate(s)) {
            Data d = data[nxt.i];
            shrink();
            it = find(data_to_key(d));
        }
        return nxt;
    }

    itr erase(const Key& key) { return erase(find(key)); }

    int count(const Key& key) { return find(key) == end() ? 0 : 1; }

    bool empty() const { return s == 0; }

    int size() const { return s; }

    void clear() {
        fill(std::begin(occupied_flag), std::end(occupied_flag), false);
        fill(std::begin(deleted_flag), std::end(deleted_flag), false);
        s = occupied = 0;
    }

    void reserve(int n) {
        if (n <= 0) return;
        n = 1 << min(23, __lg(n) + 2);
        if (cap < u32(n)) reallocate(n);
    }
};

template <typename Key, typename Data>
uint64_t HashMapBase<Key, Data>::r = chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();

}  // namespace HashMapImpl

template <typename Key, typename Val>
struct HashMap : HashMapImpl::HashMapBase<Key, pair<Key, Val>> {
    using base = typename HashMapImpl::HashMapBase<Key, pair<Key, Val>>;
    using HashMapImpl::HashMapBase<Key, pair<Key, Val>>::HashMapBase;
    using Data = pair<Key, Val>;

    Val& operator[](const Key& k) {
        typename base::u32 h = base::inner_hash(k);
        while (true) {
            if (base::occupied_flag[h] == false) {
                if (base::extend_rate(base::occupied + 1)) {
                    base::extend();
                    h = base::hash(k);
                    continue;
                }
                base::data[h].first = k;
                base::data[h].second = Val();
                base::occupied_flag[h] = true;
                ++base::occupied, ++base::s;
                return base::data[h].second;
            }
            if (base::data[h].first == k) {
                if (base::deleted_flag[h] == true) {
                    base::data[h].second = Val();
                    base::deleted_flag[h] = false;
                    ++base::s;
                }
                return base::data[h].second;
            }
            h = (h + 1) & (base::cap - 1);
        }
    }

    typename base::itr emplace(const Key& key, const Val& val) { return base::insert(Data(key, val)); }
};

template <typename Key>
struct HashSet : HashMapImpl::HashMapBase<Key, Key> {
    using HashMapImpl::HashMapBase<Key, Key>::HashMapBase;
};

constexpr int MAX = 100010;

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N, M;
    cin >> N >> M;
    vector<int> v(N), h(N);
    for (int i = 0; i < N; i++) cin >> v[i] >> h[i];
    vector<int> t(M), s(M);
    for (int i = 0; i < M; i++) {
        cin >> t[i] >> s[i];
        // s[i] は実質的に単調増加列とみなせる
        if (i - 1 >= 0) s[i] = max(s[i], s[i - 1]);
    }
    // d[i] := |h[i + 1] - h[i]|
    vector<ll> d(N - 1), accd(N), acch(N + 1), accv(N + 1);
    for (int i = 0; i + 1 < N; i++) d[i] = abs(h[i + 1] - h[i]);
    for (int i = 0; i + 1 < N; i++) accd[i + 1] = accd[i] + d[i];
    for (int i = 0; i < N; i++) {
        acch[i + 1] = acch[i] + h[i];
        accv[i + 1] = accv[i] + v[i];
    }

    // f(i, j) := [i, j) のアイテムを購入したときの強さの増分
    auto f = [&](int i, int j) -> ll { return acch[j] - acch[i] + max<ll>(0, accd[j - 1] - accd[i]); };

    // dp[i][j] := i 番目のイベント終了時,
    // 強さ j
    // のどこまでアイテムを買ったかの min
    vector<unordered_map<ll, int>> dp(M + 1);
    dp[0][0] = 0;
    for (int i = 0; i < M; i++) {
        for (auto&& [key, val] : dp[i]) {
            // 強さ key, アイテムは [0, val) まで購入
            for (int j = val + 1; j <= N; j++) {
                // [val, j) までのアイテムを購入: 強さは key + f(val, j)
                ll next_strong = key + f(val, j);
                // t[i] が [0, j) の v の総和未満なら break
                if (t[i] < accv[j]) break;
                // 次の場所まで skip (次の場所に行けない場合は continue)
                int next_event = upper_bound(s.begin(), s.end(), next_strong) - s.begin();
                if (next_event <= i) continue;
                if (dp[next_event].contains(next_strong)) {
                    dp[next_event][next_strong] = min(dp[next_event][next_strong], j);
                } else {
                    dp[next_event][next_strong] = j;
                }
            }
        }
    }

    ll ans = -1;
    for (auto&& [key, val] : dp[M]) {
        // 強さ key, アイテムは [0, val) まで購入
        ans = max(ans, t[M - 1] - accv[val]);
    }

    cout << ans << '\n';
}
accuracy: 1
time_ms: 290
memory_kb: 5248
final_rank: 11

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

#ifdef LOCAL
#include <debug.hpp>
#else
#define debug(...)
#endif

// ref: https://nyaannyaan.github.io/library/hashmap/hashmap.hpp.html
namespace HashMapImpl {
using u32 = uint32_t;
using u64 = uint64_t;

template <typename Key, typename Data>
struct HashMapBase;

template <typename Key, typename Data>
struct itrB {
    // [UPDATE] C++17 で非推奨になった std::iterator template から変更
    using iterator_category = bidirectional_iterator_tag;
    using value_type = Data;
    using difference_type = ptrdiff_t;
    using pointer = value_type*;
    using reference = value_type&;

    u32 i;
    HashMapBase<Key, Data>* p;

    explicit constexpr itrB() : i(0), p(nullptr) {}
    explicit constexpr itrB(u32 _i, HashMapBase<Key, Data>* _p) : i(_i), p(_p) {}
    explicit constexpr itrB(u32 _i, const HashMapBase<Key, Data>* _p) : i(_i), p(const_cast<HashMapBase<Key, Data>*>(_p)) {}
    friend void swap(itrB& l, itrB& r) { swap(l.i, r.i), swap(l.p, r.p); }
    friend bool operator==(const itrB& l, const itrB& r) { return l.i == r.i; }
    friend bool operator!=(const itrB& l, const itrB& r) { return l.i != r.i; }
    const reference operator*() const { return const_cast<const HashMapBase<Key, Data>*>(p)->data[i]; }
    reference operator*() { return p->data[i]; }
    pointer operator->() const { return &(p->data[i]); }

    itrB& operator++() {
        assert(i != p->cap && "itr::operator++()");
        do {
            i++;
            if (i == p->cap) break;
            if (p->occupied_flag[i] && !p->deleted_flag[i]) break;
        } while (true);
        return (*this);
    }
    itrB operator++(int) {
        itrB it(*this);
        ++(*this);
        return it;
    }
    itrB& operator--() {
        do {
            i--;
            if (p->occupied_flag[i] && !p->deleted_flag[i]) break;
            assert(i != 0 && "itr::operator--()");
        } while (true);
        return (*this);
    }
    itrB operator--(int) {
        itrB it(*this);
        --(*this);
        return it;
    }
};

template <typename Key, typename Data>
struct HashMapBase {
    using u32 = uint32_t;
    using u64 = uint64_t;
    using iterator = itrB<Key, Data>;
    using itr = iterator;

   protected:
    template <typename K>
    inline u64 randomized(const K& key) const {
        return u64(key) ^ r;
    }
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<is_integral<K>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        return (randomized(key) * 11995408973635179863ULL) >> shift;
    }
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<is_integral<decltype(K::first)>::value, nullptr_t> = nullptr, enable_if_t<is_integral<decltype(K::second)>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        u64 a = randomized(key.first), b = randomized(key.second);
        a *= 11995408973635179863ULL;
        b *= 10150724397891781847ULL;
        return (a + b) >> shift;
    }
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<is_integral<typename K::value_type>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        static constexpr u64 mod = (1LL << 61) - 1;
        static constexpr u64 base = 950699498548472943ULL;
        u64 res = 0;
        for (auto& elem : key) {
            __uint128_t x = __uint128_t(res) * base + (randomized(elem) & mod);
            res = (x & mod) + (x >> 61);
        }
        __uint128_t x = __uint128_t(res) * base;
        res = (x & mod) + (x >> 61);
        if (res >= mod) res -= mod;
        return res >> (shift - 3);
    }
    // [ADD] 数値を要素とする 2 次元コンテナ用のハッシュ関数を追加
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<!is_integral<typename K::value_type>::value, nullptr_t> = nullptr, enable_if_t<is_integral<typename K::value_type::value_type>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        static constexpr u64 mod = (1LL << 61) - 1;
        static constexpr u64 base = 950699498548472943ULL;
        u64 res = 0;
        for (auto& container : key) {
            for (auto& elem : container) {
                __uint128_t x = __uint128_t(res) * base + (randomized(elem) & mod);
                res = (x & mod) + (x >> 61);
            }
        }
        __uint128_t x = __uint128_t(res) * base;
        res = (x & mod) + (x >> 61);
        if (res >= mod) res -= mod;
        return res >> (shift - 3);
    }

    template <typename D = Data, enable_if_t<is_same<D, Key>::value, nullptr_t> = nullptr>
    inline u32 hash(const D& dat) const {
        return inner_hash(dat);
    }
    template <typename D = Data, enable_if_t<is_same<decltype(D::first), Key>::value, nullptr_t> = nullptr>
    inline u32 hash(const D& dat) const {
        return inner_hash(dat.first);
    }

    template <typename D = Data, enable_if_t<is_same<D, Key>::value, nullptr_t> = nullptr>
    inline Key data_to_key(const D& dat) const {
        return dat;
    }
    template <typename D = Data, enable_if_t<is_same<decltype(D::first), Key>::value, nullptr_t> = nullptr>
    inline Key data_to_key(const D& dat) const {
        return dat.first;
    }

    void reallocate(u32 ncap) {
        vector<Data> ndata(ncap);
        vector<bool> nf(ncap);
        shift = 64 - __lg(ncap);
        for (u32 i = 0; i < cap; i++) {
            if (occupied_flag[i] && !deleted_flag[i]) {
                u32 h = hash(data[i]);
                while (nf[h]) h = (h + 1) & (ncap - 1);
                ndata[h] = move(data[i]);
                nf[h] = true;
            }
        }
        data.swap(ndata);
        occupied_flag.swap(nf);
        cap = ncap;
        occupied = s;
        deleted_flag.resize(cap);
        fill(std::begin(deleted_flag), std::end(deleted_flag), false);
    }

    inline bool extend_rate(u32 x) const { return x * 2 >= cap; }

    inline bool shrink_rate(u32 x) const { return HASHMAP_DEFAULT_SIZE < cap && x * 10 <= cap; }

    inline void extend() { reallocate(cap << 1); }

    inline void shrink() { reallocate(cap >> 1); }

   public:
    u32 cap, s, occupied;
    vector<Data> data;
    vector<bool> occupied_flag, deleted_flag;
    u32 shift;
    static u64 r;
    static constexpr uint32_t HASHMAP_DEFAULT_SIZE = 4;

    explicit HashMapBase() : cap(HASHMAP_DEFAULT_SIZE), s(0), occupied(0), data(cap), occupied_flag(cap), deleted_flag(cap), shift(64 - __lg(cap)) {}

    itr begin() const {
        u32 h = 0;
        while (h != cap) {
            if (occupied_flag[h] && !deleted_flag[h]) break;
            h++;
        }
        return itr(h, this);
    }
    itr end() const { return itr(this->cap, this); }

    friend itr begin(const HashMapBase& h) { return h.begin(); }
    friend itr end(const HashMapBase& h) { return h.end(); }

    itr find(const Key& key) const {
        u32 h = inner_hash(key);
        while (true) {
            if (occupied_flag[h] == false) return this->end();
            if (data_to_key(data[h]) == key) {
                if (deleted_flag[h] == true) return this->end();
                return itr(h, this);
            }
            h = (h + 1) & (cap - 1);
        }
    }

    bool contain(const Key& key) const { return find(key) != this->end(); }

    itr insert(const Data& d) {
        u32 h = hash(d);
        while (true) {
            if (occupied_flag[h] == false) {
                if (extend_rate(occupied + 1)) {
                    extend();
                    h = hash(d);
                    continue;
                }
                data[h] = d;
                occupied_flag[h] = true;
                ++occupied, ++s;
                return itr(h, this);
            }
            if (data_to_key(data[h]) == data_to_key(d)) {
                if (deleted_flag[h] == true) {
                    data[h] = d;
                    deleted_flag[h] = false;
                    ++s;
                }
                return itr(h, this);
            }
            h = (h + 1) & (cap - 1);
        }
    }

    // tips for speed up :
    // if return value is unnecessary, make argument_2 false.
    itr erase(itr it, bool get_next = true) {
        if (it == this->end()) return this->end();
        s--;
        if (!get_next) {
            this->deleted_flag[it.i] = true;
            if (shrink_rate(s)) shrink();
            return this->end();
        }
        itr nxt = it;
        nxt++;
        this->deleted_flag[it.i] = true;
        if (shrink_rate(s)) {
            Data d = data[nxt.i];
            shrink();
            it = find(data_to_key(d));
        }
        return nxt;
    }

    itr erase(const Key& key) { return erase(find(key)); }

    int count(const Key& key) { return find(key) == end() ? 0 : 1; }

    bool empty() const { return s == 0; }

    int size() const { return s; }

    void clear() {
        fill(std::begin(occupied_flag), std::end(occupied_flag), false);
        fill(std::begin(deleted_flag), std::end(deleted_flag), false);
        s = occupied = 0;
    }

    void reserve(int n) {
        if (n <= 0) return;
        n = 1 << min(23, __lg(n) + 2);
        if (cap < u32(n)) reallocate(n);
    }
};

template <typename Key, typename Data>
uint64_t HashMapBase<Key, Data>::r = chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();

}  // namespace HashMapImpl

template <typename Key, typename Val>
struct HashMap : HashMapImpl::HashMapBase<Key, pair<Key, Val>> {
    using base = typename HashMapImpl::HashMapBase<Key, pair<Key, Val>>;
    using HashMapImpl::HashMapBase<Key, pair<Key, Val>>::HashMapBase;
    using Data = pair<Key, Val>;

    Val& operator[](const Key& k) {
        typename base::u32 h = base::inner_hash(k);
        while (true) {
            if (base::occupied_flag[h] == false) {
                if (base::extend_rate(base::occupied + 1)) {
                    base::extend();
                    h = base::hash(k);
                    continue;
                }
                base::data[h].first = k;
                base::data[h].second = Val();
                base::occupied_flag[h] = true;
                ++base::occupied, ++base::s;
                return base::data[h].second;
            }
            if (base::data[h].first == k) {
                if (base::deleted_flag[h] == true) {
                    base::data[h].second = Val();
                    base::deleted_flag[h] = false;
                    ++base::s;
                }
                return base::data[h].second;
            }
            h = (h + 1) & (base::cap - 1);
        }
    }

    typename base::itr emplace(const Key& key, const Val& val) { return base::insert(Data(key, val)); }
};

template <typename Key>
struct HashSet : HashMapImpl::HashMapBase<Key, Key> {
    using HashMapImpl::HashMapBase<Key, Key>::HashMapBase;
};

constexpr int MAX = 100010;
// int v[MAX], h[MAX], t[MAX], s[MAX];
// ll d[MAX], accd[MAX], acch[MAX], accv[MAX];
// HashMap<ll, int> dp[MAX];

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N, M;
    cin >> N >> M;
    vector<int> v(N), h(N);
    for (int i = 0; i < N; i++) cin >> v[i] >> h[i];
    vector<int> t(M), s(M);
    for (int i = 0; i < M; i++) {
        cin >> t[i] >> s[i];
        // s[i] は実質的に単調増加列とみなせる
        if (i - 1 >= 0) s[i] = max(s[i], s[i - 1]);
    }
    // d[i] := |h[i + 1] - h[i]|
    vector<ll> d(N - 1), accd(N), acch(N + 1), accv(N + 1);
    for (int i = 0; i + 1 < N; i++) d[i] = abs(h[i + 1] - h[i]);
    for (int i = 0; i + 1 < N; i++) accd[i + 1] = accd[i] + d[i];
    for (int i = 0; i < N; i++) {
        acch[i + 1] = acch[i] + h[i];
        accv[i + 1] = accv[i] + v[i];
    }

    // f(i, j) := [i, j) のアイテムを購入したときの強さの増分
    auto f = [&](int i, int j) -> ll { return acch[j] - acch[i] + max<ll>(0, accd[j - 1] - accd[i]); };

    // dp[i][j] := i 番目のイベント終了時,
    // 強さ j
    // のどこまでアイテムを買ったかの min
    vector<unordered_map<ll, int>> dp(M + 1);
    dp[0][0] = 0;
    for (int i = 0; i < M; i++) {
        for (auto&& [key, val] : dp[i]) {
            // 強さ key, アイテムは [0, val) まで購入
            for (int j = val + 1; j <= N; j++) {
                // [val, j) までのアイテムを購入: 強さは key + f(val, j)
                ll next_strong = key + f(val, j);
                // t[i] が [0, j) の v の総和未満なら break
                if (t[i] < accv[j]) break;
                // 次の場所まで skip (次の場所に行けない場合は continue)
                int next_event = upper_bound(s.begin(), s.end(), next_strong) - s.begin();
                if (next_event <= i) continue;
                if (dp[next_event].contains(next_strong)) {
                    dp[next_event][next_strong] = min(dp[next_event][next_strong], j);
                } else {
                    dp[next_event][next_strong] = j;
                }
            }
        }
    }

    ll ans = -1;
    for (auto&& [key, val] : dp[M]) {
        // 強さ key, アイテムは [0, val) まで購入
        ans = max(ans, t[M - 1] - accv[val]);
    }

    cout << ans << '\n';
}
accuracy: 1
time_ms: 280
memory_kb: 5248
final_rank: 10

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

#ifdef LOCAL
#include <debug.hpp>
#else
#define debug(...)
#endif

// ref: https://nyaannyaan.github.io/library/hashmap/hashmap.hpp.html
namespace HashMapImpl {
using u32 = uint32_t;
using u64 = uint64_t;

template <typename Key, typename Data>
struct HashMapBase;

template <typename Key, typename Data>
struct itrB {
    // [UPDATE] C++17 で非推奨になった std::iterator template から変更
    using iterator_category = bidirectional_iterator_tag;
    using value_type = Data;
    using difference_type = ptrdiff_t;
    using pointer = value_type*;
    using reference = value_type&;

    u32 i;
    HashMapBase<Key, Data>* p;

    explicit constexpr itrB() : i(0), p(nullptr) {}
    explicit constexpr itrB(u32 _i, HashMapBase<Key, Data>* _p) : i(_i), p(_p) {}
    explicit constexpr itrB(u32 _i, const HashMapBase<Key, Data>* _p) : i(_i), p(const_cast<HashMapBase<Key, Data>*>(_p)) {}
    friend void swap(itrB& l, itrB& r) { swap(l.i, r.i), swap(l.p, r.p); }
    friend bool operator==(const itrB& l, const itrB& r) { return l.i == r.i; }
    friend bool operator!=(const itrB& l, const itrB& r) { return l.i != r.i; }
    const reference operator*() const { return const_cast<const HashMapBase<Key, Data>*>(p)->data[i]; }
    reference operator*() { return p->data[i]; }
    pointer operator->() const { return &(p->data[i]); }

    itrB& operator++() {
        assert(i != p->cap && "itr::operator++()");
        do {
            i++;
            if (i == p->cap) break;
            if (p->occupied_flag[i] && !p->deleted_flag[i]) break;
        } while (true);
        return (*this);
    }
    itrB operator++(int) {
        itrB it(*this);
        ++(*this);
        return it;
    }
    itrB& operator--() {
        do {
            i--;
            if (p->occupied_flag[i] && !p->deleted_flag[i]) break;
            assert(i != 0 && "itr::operator--()");
        } while (true);
        return (*this);
    }
    itrB operator--(int) {
        itrB it(*this);
        --(*this);
        return it;
    }
};

template <typename Key, typename Data>
struct HashMapBase {
    using u32 = uint32_t;
    using u64 = uint64_t;
    using iterator = itrB<Key, Data>;
    using itr = iterator;

   protected:
    template <typename K>
    inline u64 randomized(const K& key) const {
        return u64(key) ^ r;
    }
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<is_integral<K>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        return (randomized(key) * 11995408973635179863ULL) >> shift;
    }
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<is_integral<decltype(K::first)>::value, nullptr_t> = nullptr, enable_if_t<is_integral<decltype(K::second)>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        u64 a = randomized(key.first), b = randomized(key.second);
        a *= 11995408973635179863ULL;
        b *= 10150724397891781847ULL;
        return (a + b) >> shift;
    }
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<is_integral<typename K::value_type>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        static constexpr u64 mod = (1LL << 61) - 1;
        static constexpr u64 base = 950699498548472943ULL;
        u64 res = 0;
        for (auto& elem : key) {
            __uint128_t x = __uint128_t(res) * base + (randomized(elem) & mod);
            res = (x & mod) + (x >> 61);
        }
        __uint128_t x = __uint128_t(res) * base;
        res = (x & mod) + (x >> 61);
        if (res >= mod) res -= mod;
        return res >> (shift - 3);
    }
    // [ADD] 数値を要素とする 2 次元コンテナ用のハッシュ関数を追加
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<!is_integral<typename K::value_type>::value, nullptr_t> = nullptr, enable_if_t<is_integral<typename K::value_type::value_type>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        static constexpr u64 mod = (1LL << 61) - 1;
        static constexpr u64 base = 950699498548472943ULL;
        u64 res = 0;
        for (auto& container : key) {
            for (auto& elem : container) {
                __uint128_t x = __uint128_t(res) * base + (randomized(elem) & mod);
                res = (x & mod) + (x >> 61);
            }
        }
        __uint128_t x = __uint128_t(res) * base;
        res = (x & mod) + (x >> 61);
        if (res >= mod) res -= mod;
        return res >> (shift - 3);
    }

    template <typename D = Data, enable_if_t<is_same<D, Key>::value, nullptr_t> = nullptr>
    inline u32 hash(const D& dat) const {
        return inner_hash(dat);
    }
    template <typename D = Data, enable_if_t<is_same<decltype(D::first), Key>::value, nullptr_t> = nullptr>
    inline u32 hash(const D& dat) const {
        return inner_hash(dat.first);
    }

    template <typename D = Data, enable_if_t<is_same<D, Key>::value, nullptr_t> = nullptr>
    inline Key data_to_key(const D& dat) const {
        return dat;
    }
    template <typename D = Data, enable_if_t<is_same<decltype(D::first), Key>::value, nullptr_t> = nullptr>
    inline Key data_to_key(const D& dat) const {
        return dat.first;
    }

    void reallocate(u32 ncap) {
        vector<Data> ndata(ncap);
        vector<bool> nf(ncap);
        shift = 64 - __lg(ncap);
        for (u32 i = 0; i < cap; i++) {
            if (occupied_flag[i] && !deleted_flag[i]) {
                u32 h = hash(data[i]);
                while (nf[h]) h = (h + 1) & (ncap - 1);
                ndata[h] = move(data[i]);
                nf[h] = true;
            }
        }
        data.swap(ndata);
        occupied_flag.swap(nf);
        cap = ncap;
        occupied = s;
        deleted_flag.resize(cap);
        fill(std::begin(deleted_flag), std::end(deleted_flag), false);
    }

    inline bool extend_rate(u32 x) const { return x * 2 >= cap; }

    inline bool shrink_rate(u32 x) const { return HASHMAP_DEFAULT_SIZE < cap && x * 10 <= cap; }

    inline void extend() { reallocate(cap << 1); }

    inline void shrink() { reallocate(cap >> 1); }

   public:
    u32 cap, s, occupied;
    vector<Data> data;
    vector<bool> occupied_flag, deleted_flag;
    u32 shift;
    static u64 r;
    static constexpr uint32_t HASHMAP_DEFAULT_SIZE = 4;

    explicit HashMapBase() : cap(HASHMAP_DEFAULT_SIZE), s(0), occupied(0), data(cap), occupied_flag(cap), deleted_flag(cap), shift(64 - __lg(cap)) {}

    itr begin() const {
        u32 h = 0;
        while (h != cap) {
            if (occupied_flag[h] && !deleted_flag[h]) break;
            h++;
        }
        return itr(h, this);
    }
    itr end() const { return itr(this->cap, this); }

    friend itr begin(const HashMapBase& h) { return h.begin(); }
    friend itr end(const HashMapBase& h) { return h.end(); }

    itr find(const Key& key) const {
        u32 h = inner_hash(key);
        while (true) {
            if (occupied_flag[h] == false) return this->end();
            if (data_to_key(data[h]) == key) {
                if (deleted_flag[h] == true) return this->end();
                return itr(h, this);
            }
            h = (h + 1) & (cap - 1);
        }
    }

    bool contain(const Key& key) const { return find(key) != this->end(); }

    itr insert(const Data& d) {
        u32 h = hash(d);
        while (true) {
            if (occupied_flag[h] == false) {
                if (extend_rate(occupied + 1)) {
                    extend();
                    h = hash(d);
                    continue;
                }
                data[h] = d;
                occupied_flag[h] = true;
                ++occupied, ++s;
                return itr(h, this);
            }
            if (data_to_key(data[h]) == data_to_key(d)) {
                if (deleted_flag[h] == true) {
                    data[h] = d;
                    deleted_flag[h] = false;
                    ++s;
                }
                return itr(h, this);
            }
            h = (h + 1) & (cap - 1);
        }
    }

    // tips for speed up :
    // if return value is unnecessary, make argument_2 false.
    itr erase(itr it, bool get_next = true) {
        if (it == this->end()) return this->end();
        s--;
        if (!get_next) {
            this->deleted_flag[it.i] = true;
            if (shrink_rate(s)) shrink();
            return this->end();
        }
        itr nxt = it;
        nxt++;
        this->deleted_flag[it.i] = true;
        if (shrink_rate(s)) {
            Data d = data[nxt.i];
            shrink();
            it = find(data_to_key(d));
        }
        return nxt;
    }

    itr erase(const Key& key) { return erase(find(key)); }

    int count(const Key& key) { return find(key) == end() ? 0 : 1; }

    bool empty() const { return s == 0; }

    int size() const { return s; }

    void clear() {
        fill(std::begin(occupied_flag), std::end(occupied_flag), false);
        fill(std::begin(deleted_flag), std::end(deleted_flag), false);
        s = occupied = 0;
    }

    void reserve(int n) {
        if (n <= 0) return;
        n = 1 << min(23, __lg(n) + 2);
        if (cap < u32(n)) reallocate(n);
    }
};

template <typename Key, typename Data>
uint64_t HashMapBase<Key, Data>::r = chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();

}  // namespace HashMapImpl

template <typename Key, typename Val>
struct HashMap : HashMapImpl::HashMapBase<Key, pair<Key, Val>> {
    using base = typename HashMapImpl::HashMapBase<Key, pair<Key, Val>>;
    using HashMapImpl::HashMapBase<Key, pair<Key, Val>>::HashMapBase;
    using Data = pair<Key, Val>;

    Val& operator[](const Key& k) {
        typename base::u32 h = base::inner_hash(k);
        while (true) {
            if (base::occupied_flag[h] == false) {
                if (base::extend_rate(base::occupied + 1)) {
                    base::extend();
                    h = base::hash(k);
                    continue;
                }
                base::data[h].first = k;
                base::data[h].second = Val();
                base::occupied_flag[h] = true;
                ++base::occupied, ++base::s;
                return base::data[h].second;
            }
            if (base::data[h].first == k) {
                if (base::deleted_flag[h] == true) {
                    base::data[h].second = Val();
                    base::deleted_flag[h] = false;
                    ++base::s;
                }
                return base::data[h].second;
            }
            h = (h + 1) & (base::cap - 1);
        }
    }

    typename base::itr emplace(const Key& key, const Val& val) { return base::insert(Data(key, val)); }
};

template <typename Key>
struct HashSet : HashMapImpl::HashMapBase<Key, Key> {
    using HashMapImpl::HashMapBase<Key, Key>::HashMapBase;
};

constexpr int MAX = 100010;
// int v[MAX], h[MAX], t[MAX], s[MAX];
// ll d[MAX], accd[MAX], acch[MAX], accv[MAX];
// HashMap<ll, int> dp[MAX];

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N, M;
    cin >> N >> M;
    vector<int> v(N), h(N);
    for (int i = 0; i < N; i++) cin >> v[i] >> h[i];
    vector<int> t(M), s(M);
    for (int i = 0; i < M; i++) {
        cin >> t[i] >> s[i];
        // s[i] は実質的に単調増加列とみなせる
        if (i - 1 >= 0) s[i] = max(s[i], s[i - 1]);
    }
    // d[i] := |h[i + 1] - h[i]|
    vector<ll> d(N - 1), accd(N), acch(N + 1), accv(N + 1);
    for (int i = 0; i + 1 < N; i++) d[i] = abs(h[i + 1] - h[i]);
    for (int i = 0; i + 1 < N; i++) accd[i + 1] = accd[i] + d[i];
    for (int i = 0; i < N; i++) {
        acch[i + 1] = acch[i] + h[i];
        accv[i + 1] = accv[i] + v[i];
    }

    // f(i, j) := [i, j) のアイテムを購入したときの強さの増分
    auto f = [&](int i, int j) -> ll { return acch[j] - acch[i] + max<ll>(0, accd[j - 1] - accd[i]); };

    // dp[i][j] := i 番目のイベント終了時,
    // 強さ j
    // のどこまでアイテムを買ったかの min
    vector<HashMap<ll, int>> dp(M + 1);
    dp[0][0] = 0;
    for (int i = 0; i < M; i++) {
        for (auto&& [key, val] : dp[i]) {
            // 強さ key, アイテムは [0, val) まで購入
            for (int j = val + 1; j <= N; j++) {
                // [val, j) までのアイテムを購入: 強さは key + f(val, j)
                ll next_strong = key + f(val, j);
                // t[i] が [0, j) の v の総和未満なら break
                if (t[i] < accv[j]) break;
                // 次の場所まで skip (次の場所に行けない場合は continue)
                int next_event = upper_bound(s.begin(), s.end(), next_strong) - s.begin();
                if (next_event <= i) continue;
                if (dp[next_event].contain(next_strong)) {
                    dp[next_event][next_strong] = min(dp[next_event][next_strong], j);
                } else {
                    dp[next_event][next_strong] = j;
                }
            }
        }
    }

    ll ans = -1;
    for (auto&& [key, val] : dp[M]) {
        // 強さ key, アイテムは [0, val) まで購入
        ans = max(ans, t[M - 1] - accv[val]);
    }

    cout << ans << '\n';
}
accuracy: 1
time_ms: 340
memory_kb: 5616
final_rank: 13

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

#ifdef LOCAL
#include <debug.hpp>
#else
#define debug(...)
#endif

// ref: https://nyaannyaan.github.io/library/hashmap/hashmap.hpp.html
namespace HashMapImpl {
using u32 = uint32_t;
using u64 = uint64_t;

template <typename Key, typename Data>
struct HashMapBase;

template <typename Key, typename Data>
struct itrB {
    // [UPDATE] C++17 で非推奨になった std::iterator template から変更
    using iterator_category = bidirectional_iterator_tag;
    using value_type = Data;
    using difference_type = ptrdiff_t;
    using pointer = value_type*;
    using reference = value_type&;

    u32 i;
    HashMapBase<Key, Data>* p;

    explicit constexpr itrB() : i(0), p(nullptr) {}
    explicit constexpr itrB(u32 _i, HashMapBase<Key, Data>* _p) : i(_i), p(_p) {}
    explicit constexpr itrB(u32 _i, const HashMapBase<Key, Data>* _p) : i(_i), p(const_cast<HashMapBase<Key, Data>*>(_p)) {}
    friend void swap(itrB& l, itrB& r) { swap(l.i, r.i), swap(l.p, r.p); }
    friend bool operator==(const itrB& l, const itrB& r) { return l.i == r.i; }
    friend bool operator!=(const itrB& l, const itrB& r) { return l.i != r.i; }
    const reference operator*() const { return const_cast<const HashMapBase<Key, Data>*>(p)->data[i]; }
    reference operator*() { return p->data[i]; }
    pointer operator->() const { return &(p->data[i]); }

    itrB& operator++() {
        assert(i != p->cap && "itr::operator++()");
        do {
            i++;
            if (i == p->cap) break;
            if (p->occupied_flag[i] && !p->deleted_flag[i]) break;
        } while (true);
        return (*this);
    }
    itrB operator++(int) {
        itrB it(*this);
        ++(*this);
        return it;
    }
    itrB& operator--() {
        do {
            i--;
            if (p->occupied_flag[i] && !p->deleted_flag[i]) break;
            assert(i != 0 && "itr::operator--()");
        } while (true);
        return (*this);
    }
    itrB operator--(int) {
        itrB it(*this);
        --(*this);
        return it;
    }
};

template <typename Key, typename Data>
struct HashMapBase {
    using u32 = uint32_t;
    using u64 = uint64_t;
    using iterator = itrB<Key, Data>;
    using itr = iterator;

   protected:
    template <typename K>
    inline u64 randomized(const K& key) const {
        return u64(key) ^ r;
    }
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<is_integral<K>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        return (randomized(key) * 11995408973635179863ULL) >> shift;
    }
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<is_integral<decltype(K::first)>::value, nullptr_t> = nullptr, enable_if_t<is_integral<decltype(K::second)>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        u64 a = randomized(key.first), b = randomized(key.second);
        a *= 11995408973635179863ULL;
        b *= 10150724397891781847ULL;
        return (a + b) >> shift;
    }
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<is_integral<typename K::value_type>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        static constexpr u64 mod = (1LL << 61) - 1;
        static constexpr u64 base = 950699498548472943ULL;
        u64 res = 0;
        for (auto& elem : key) {
            __uint128_t x = __uint128_t(res) * base + (randomized(elem) & mod);
            res = (x & mod) + (x >> 61);
        }
        __uint128_t x = __uint128_t(res) * base;
        res = (x & mod) + (x >> 61);
        if (res >= mod) res -= mod;
        return res >> (shift - 3);
    }
    // [ADD] 数値を要素とする 2 次元コンテナ用のハッシュ関数を追加
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<!is_integral<typename K::value_type>::value, nullptr_t> = nullptr, enable_if_t<is_integral<typename K::value_type::value_type>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        static constexpr u64 mod = (1LL << 61) - 1;
        static constexpr u64 base = 950699498548472943ULL;
        u64 res = 0;
        for (auto& container : key) {
            for (auto& elem : container) {
                __uint128_t x = __uint128_t(res) * base + (randomized(elem) & mod);
                res = (x & mod) + (x >> 61);
            }
        }
        __uint128_t x = __uint128_t(res) * base;
        res = (x & mod) + (x >> 61);
        if (res >= mod) res -= mod;
        return res >> (shift - 3);
    }

    template <typename D = Data, enable_if_t<is_same<D, Key>::value, nullptr_t> = nullptr>
    inline u32 hash(const D& dat) const {
        return inner_hash(dat);
    }
    template <typename D = Data, enable_if_t<is_same<decltype(D::first), Key>::value, nullptr_t> = nullptr>
    inline u32 hash(const D& dat) const {
        return inner_hash(dat.first);
    }

    template <typename D = Data, enable_if_t<is_same<D, Key>::value, nullptr_t> = nullptr>
    inline Key data_to_key(const D& dat) const {
        return dat;
    }
    template <typename D = Data, enable_if_t<is_same<decltype(D::first), Key>::value, nullptr_t> = nullptr>
    inline Key data_to_key(const D& dat) const {
        return dat.first;
    }

    void reallocate(u32 ncap) {
        vector<Data> ndata(ncap);
        vector<bool> nf(ncap);
        shift = 64 - __lg(ncap);
        for (u32 i = 0; i < cap; i++) {
            if (occupied_flag[i] && !deleted_flag[i]) {
                u32 h = hash(data[i]);
                while (nf[h]) h = (h + 1) & (ncap - 1);
                ndata[h] = move(data[i]);
                nf[h] = true;
            }
        }
        data.swap(ndata);
        occupied_flag.swap(nf);
        cap = ncap;
        occupied = s;
        deleted_flag.resize(cap);
        fill(std::begin(deleted_flag), std::end(deleted_flag), false);
    }

    inline bool extend_rate(u32 x) const { return x * 2 >= cap; }

    inline bool shrink_rate(u32 x) const { return HASHMAP_DEFAULT_SIZE < cap && x * 10 <= cap; }

    inline void extend() { reallocate(cap << 1); }

    inline void shrink() { reallocate(cap >> 1); }

   public:
    u32 cap, s, occupied;
    vector<Data> data;
    vector<bool> occupied_flag, deleted_flag;
    u32 shift;
    static u64 r;
    static constexpr uint32_t HASHMAP_DEFAULT_SIZE = 4;

    explicit HashMapBase() : cap(HASHMAP_DEFAULT_SIZE), s(0), occupied(0), data(cap), occupied_flag(cap), deleted_flag(cap), shift(64 - __lg(cap)) {}

    itr begin() const {
        u32 h = 0;
        while (h != cap) {
            if (occupied_flag[h] && !deleted_flag[h]) break;
            h++;
        }
        return itr(h, this);
    }
    itr end() const { return itr(this->cap, this); }

    friend itr begin(const HashMapBase& h) { return h.begin(); }
    friend itr end(const HashMapBase& h) { return h.end(); }

    itr find(const Key& key) const {
        u32 h = inner_hash(key);
        while (true) {
            if (occupied_flag[h] == false) return this->end();
            if (data_to_key(data[h]) == key) {
                if (deleted_flag[h] == true) return this->end();
                return itr(h, this);
            }
            h = (h + 1) & (cap - 1);
        }
    }

    bool contain(const Key& key) const { return find(key) != this->end(); }

    itr insert(const Data& d) {
        u32 h = hash(d);
        while (true) {
            if (occupied_flag[h] == false) {
                if (extend_rate(occupied + 1)) {
                    extend();
                    h = hash(d);
                    continue;
                }
                data[h] = d;
                occupied_flag[h] = true;
                ++occupied, ++s;
                return itr(h, this);
            }
            if (data_to_key(data[h]) == data_to_key(d)) {
                if (deleted_flag[h] == true) {
                    data[h] = d;
                    deleted_flag[h] = false;
                    ++s;
                }
                return itr(h, this);
            }
            h = (h + 1) & (cap - 1);
        }
    }

    // tips for speed up :
    // if return value is unnecessary, make argument_2 false.
    itr erase(itr it, bool get_next = true) {
        if (it == this->end()) return this->end();
        s--;
        if (!get_next) {
            this->deleted_flag[it.i] = true;
            if (shrink_rate(s)) shrink();
            return this->end();
        }
        itr nxt = it;
        nxt++;
        this->deleted_flag[it.i] = true;
        if (shrink_rate(s)) {
            Data d = data[nxt.i];
            shrink();
            it = find(data_to_key(d));
        }
        return nxt;
    }

    itr erase(const Key& key) { return erase(find(key)); }

    int count(const Key& key) { return find(key) == end() ? 0 : 1; }

    bool empty() const { return s == 0; }

    int size() const { return s; }

    void clear() {
        fill(std::begin(occupied_flag), std::end(occupied_flag), false);
        fill(std::begin(deleted_flag), std::end(deleted_flag), false);
        s = occupied = 0;
    }

    void reserve(int n) {
        if (n <= 0) return;
        n = 1 << min(23, __lg(n) + 2);
        if (cap < u32(n)) reallocate(n);
    }
};

template <typename Key, typename Data>
uint64_t HashMapBase<Key, Data>::r = chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();

}  // namespace HashMapImpl

template <typename Key, typename Val>
struct HashMap : HashMapImpl::HashMapBase<Key, pair<Key, Val>> {
    using base = typename HashMapImpl::HashMapBase<Key, pair<Key, Val>>;
    using HashMapImpl::HashMapBase<Key, pair<Key, Val>>::HashMapBase;
    using Data = pair<Key, Val>;

    Val& operator[](const Key& k) {
        typename base::u32 h = base::inner_hash(k);
        while (true) {
            if (base::occupied_flag[h] == false) {
                if (base::extend_rate(base::occupied + 1)) {
                    base::extend();
                    h = base::hash(k);
                    continue;
                }
                base::data[h].first = k;
                base::data[h].second = Val();
                base::occupied_flag[h] = true;
                ++base::occupied, ++base::s;
                return base::data[h].second;
            }
            if (base::data[h].first == k) {
                if (base::deleted_flag[h] == true) {
                    base::data[h].second = Val();
                    base::deleted_flag[h] = false;
                    ++base::s;
                }
                return base::data[h].second;
            }
            h = (h + 1) & (base::cap - 1);
        }
    }

    typename base::itr emplace(const Key& key, const Val& val) { return base::insert(Data(key, val)); }
};

template <typename Key>
struct HashSet : HashMapImpl::HashMapBase<Key, Key> {
    using HashMapImpl::HashMapBase<Key, Key>::HashMapBase;
};

constexpr int MAX = 100010;
int v[MAX], h[MAX], t[MAX], s[MAX];
ll d[MAX], accd[MAX], acch[MAX], accv[MAX];
HashMap<ll, int> dp[MAX];

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N, M;
    cin >> N >> M;
    // vector<int> v(N), h(N);
    for (int i = 0; i < N; i++) cin >> v[i] >> h[i];
    // vector<int> t(M), s(M);
    for (int i = 0; i < M; i++) {
        cin >> t[i] >> s[i];
        // s[i] は実質的に単調増加列とみなせる
        if (i - 1 >= 0) s[i] = max(s[i], s[i - 1]);
    }
    // d[i] := |h[i + 1] - h[i]|
    // vector<ll> d(N - 1), accd(N), acch(N + 1), accv(N + 1);
    for (int i = 0; i + 1 < N; i++) d[i] = abs(h[i + 1] - h[i]);
    for (int i = 0; i + 1 < N; i++) accd[i + 1] = accd[i] + d[i];
    for (int i = 0; i < N; i++) {
        acch[i + 1] = acch[i] + h[i];
        accv[i + 1] = accv[i] + v[i];
    }

    // f(i, j) := [i, j) のアイテムを購入したときの強さの増分
    auto f = [&](int i, int j) -> ll { return acch[j] - acch[i] + max<ll>(0, accd[j - 1] - accd[i]); };

    // dp[i][j] := i 番目のイベント終了時,
    // 強さ j
    // のどこまでアイテムを買ったかの min
    // vector<HashMap<ll, int>> dp(M + 1);
    dp[0][0] = 0;
    for (int i = 0; i < M; i++) {
        for (auto&& [key, val] : dp[i]) {
            // 強さ key, アイテムは [0, val) まで購入
            for (int j = val + 1; j <= N; j++) {
                // [val, j) までのアイテムを購入: 強さは key + f(val, j)
                ll next_strong = key + f(val, j);
                // t[i] が [0, j) の v の総和未満なら break
                if (t[i] < accv[j]) break;
                // 次の場所まで skip (次の場所に行けない場合は continue)
                int next_event = upper_bound(s, s + M, next_strong) - s;
                if (next_event <= i) continue;
                if (dp[next_event].contain(next_strong)) {
                    dp[next_event][next_strong] = min(dp[next_event][next_strong], j);
                } else {
                    dp[next_event][next_strong] = j;
                }
            }
        }
    }

    ll ans = -1;
    for (auto&& [key, val] : dp[M]) {
        // 強さ key, アイテムは [0, val) まで購入
        ans = max(ans, t[M - 1] - accv[val]);
    }

    cout << ans << '\n';
}
accuracy: 1
time_ms: 310
memory_kb: 35660
final_rank: 15

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

#ifdef LOCAL
#include <debug.hpp>
#else
#define debug(...)
#endif

// ref: https://nyaannyaan.github.io/library/hashmap/hashmap.hpp.html
namespace HashMapImpl {
using u32 = uint32_t;
using u64 = uint64_t;

template <typename Key, typename Data>
struct HashMapBase;

template <typename Key, typename Data>
struct itrB {
    // [UPDATE] C++17 で非推奨になった std::iterator template から変更
    using iterator_category = bidirectional_iterator_tag;
    using value_type = Data;
    using difference_type = ptrdiff_t;
    using pointer = value_type*;
    using reference = value_type&;

    u32 i;
    HashMapBase<Key, Data>* p;

    explicit constexpr itrB() : i(0), p(nullptr) {}
    explicit constexpr itrB(u32 _i, HashMapBase<Key, Data>* _p) : i(_i), p(_p) {}
    explicit constexpr itrB(u32 _i, const HashMapBase<Key, Data>* _p) : i(_i), p(const_cast<HashMapBase<Key, Data>*>(_p)) {}
    friend void swap(itrB& l, itrB& r) { swap(l.i, r.i), swap(l.p, r.p); }
    friend bool operator==(const itrB& l, const itrB& r) { return l.i == r.i; }
    friend bool operator!=(const itrB& l, const itrB& r) { return l.i != r.i; }
    const reference operator*() const { return const_cast<const HashMapBase<Key, Data>*>(p)->data[i]; }
    reference operator*() { return p->data[i]; }
    pointer operator->() const { return &(p->data[i]); }

    itrB& operator++() {
        assert(i != p->cap && "itr::operator++()");
        do {
            i++;
            if (i == p->cap) break;
            if (p->occupied_flag[i] && !p->deleted_flag[i]) break;
        } while (true);
        return (*this);
    }
    itrB operator++(int) {
        itrB it(*this);
        ++(*this);
        return it;
    }
    itrB& operator--() {
        do {
            i--;
            if (p->occupied_flag[i] && !p->deleted_flag[i]) break;
            assert(i != 0 && "itr::operator--()");
        } while (true);
        return (*this);
    }
    itrB operator--(int) {
        itrB it(*this);
        --(*this);
        return it;
    }
};

template <typename Key, typename Data>
struct HashMapBase {
    using u32 = uint32_t;
    using u64 = uint64_t;
    using iterator = itrB<Key, Data>;
    using itr = iterator;

   protected:
    template <typename K>
    inline u64 randomized(const K& key) const {
        return u64(key) ^ r;
    }
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<is_integral<K>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        return (randomized(key) * 11995408973635179863ULL) >> shift;
    }
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<is_integral<decltype(K::first)>::value, nullptr_t> = nullptr, enable_if_t<is_integral<decltype(K::second)>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        u64 a = randomized(key.first), b = randomized(key.second);
        a *= 11995408973635179863ULL;
        b *= 10150724397891781847ULL;
        return (a + b) >> shift;
    }
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<is_integral<typename K::value_type>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        static constexpr u64 mod = (1LL << 61) - 1;
        static constexpr u64 base = 950699498548472943ULL;
        u64 res = 0;
        for (auto& elem : key) {
            __uint128_t x = __uint128_t(res) * base + (randomized(elem) & mod);
            res = (x & mod) + (x >> 61);
        }
        __uint128_t x = __uint128_t(res) * base;
        res = (x & mod) + (x >> 61);
        if (res >= mod) res -= mod;
        return res >> (shift - 3);
    }
    // [ADD] 数値を要素とする 2 次元コンテナ用のハッシュ関数を追加
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<!is_integral<typename K::value_type>::value, nullptr_t> = nullptr, enable_if_t<is_integral<typename K::value_type::value_type>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K& key) const {
        static constexpr u64 mod = (1LL << 61) - 1;
        static constexpr u64 base = 950699498548472943ULL;
        u64 res = 0;
        for (auto& container : key) {
            for (auto& elem : container) {
                __uint128_t x = __uint128_t(res) * base + (randomized(elem) & mod);
                res = (x & mod) + (x >> 61);
            }
        }
        __uint128_t x = __uint128_t(res) * base;
        res = (x & mod) + (x >> 61);
        if (res >= mod) res -= mod;
        return res >> (shift - 3);
    }

    template <typename D = Data, enable_if_t<is_same<D, Key>::value, nullptr_t> = nullptr>
    inline u32 hash(const D& dat) const {
        return inner_hash(dat);
    }
    template <typename D = Data, enable_if_t<is_same<decltype(D::first), Key>::value, nullptr_t> = nullptr>
    inline u32 hash(const D& dat) const {
        return inner_hash(dat.first);
    }

    template <typename D = Data, enable_if_t<is_same<D, Key>::value, nullptr_t> = nullptr>
    inline Key data_to_key(const D& dat) const {
        return dat;
    }
    template <typename D = Data, enable_if_t<is_same<decltype(D::first), Key>::value, nullptr_t> = nullptr>
    inline Key data_to_key(const D& dat) const {
        return dat.first;
    }

    void reallocate(u32 ncap) {
        vector<Data> ndata(ncap);
        vector<bool> nf(ncap);
        shift = 64 - __lg(ncap);
        for (u32 i = 0; i < cap; i++) {
            if (occupied_flag[i] && !deleted_flag[i]) {
                u32 h = hash(data[i]);
                while (nf[h]) h = (h + 1) & (ncap - 1);
                ndata[h] = move(data[i]);
                nf[h] = true;
            }
        }
        data.swap(ndata);
        occupied_flag.swap(nf);
        cap = ncap;
        occupied = s;
        deleted_flag.resize(cap);
        fill(std::begin(deleted_flag), std::end(deleted_flag), false);
    }

    inline bool extend_rate(u32 x) const { return x * 2 >= cap; }

    inline bool shrink_rate(u32 x) const { return HASHMAP_DEFAULT_SIZE < cap && x * 10 <= cap; }

    inline void extend() { reallocate(cap << 1); }

    inline void shrink() { reallocate(cap >> 1); }

   public:
    u32 cap, s, occupied;
    vector<Data> data;
    vector<bool> occupied_flag, deleted_flag;
    u32 shift;
    static u64 r;
    static constexpr uint32_t HASHMAP_DEFAULT_SIZE = 4;

    explicit HashMapBase() : cap(HASHMAP_DEFAULT_SIZE), s(0), occupied(0), data(cap), occupied_flag(cap), deleted_flag(cap), shift(64 - __lg(cap)) {}

    itr begin() const {
        u32 h = 0;
        while (h != cap) {
            if (occupied_flag[h] && !deleted_flag[h]) break;
            h++;
        }
        return itr(h, this);
    }
    itr end() const { return itr(this->cap, this); }

    friend itr begin(const HashMapBase& h) { return h.begin(); }
    friend itr end(const HashMapBase& h) { return h.end(); }

    itr find(const Key& key) const {
        u32 h = inner_hash(key);
        while (true) {
            if (occupied_flag[h] == false) return this->end();
            if (data_to_key(data[h]) == key) {
                if (deleted_flag[h] == true) return this->end();
                return itr(h, this);
            }
            h = (h + 1) & (cap - 1);
        }
    }

    bool contain(const Key& key) const { return find(key) != this->end(); }

    itr insert(const Data& d) {
        u32 h = hash(d);
        while (true) {
            if (occupied_flag[h] == false) {
                if (extend_rate(occupied + 1)) {
                    extend();
                    h = hash(d);
                    continue;
                }
                data[h] = d;
                occupied_flag[h] = true;
                ++occupied, ++s;
                return itr(h, this);
            }
            if (data_to_key(data[h]) == data_to_key(d)) {
                if (deleted_flag[h] == true) {
                    data[h] = d;
                    deleted_flag[h] = false;
                    ++s;
                }
                return itr(h, this);
            }
            h = (h + 1) & (cap - 1);
        }
    }

    // tips for speed up :
    // if return value is unnecessary, make argument_2 false.
    itr erase(itr it, bool get_next = true) {
        if (it == this->end()) return this->end();
        s--;
        if (!get_next) {
            this->deleted_flag[it.i] = true;
            if (shrink_rate(s)) shrink();
            return this->end();
        }
        itr nxt = it;
        nxt++;
        this->deleted_flag[it.i] = true;
        if (shrink_rate(s)) {
            Data d = data[nxt.i];
            shrink();
            it = find(data_to_key(d));
        }
        return nxt;
    }

    itr erase(const Key& key) { return erase(find(key)); }

    int count(const Key& key) { return find(key) == end() ? 0 : 1; }

    bool empty() const { return s == 0; }

    int size() const { return s; }

    void clear() {
        fill(std::begin(occupied_flag), std::end(occupied_flag), false);
        fill(std::begin(deleted_flag), std::end(deleted_flag), false);
        s = occupied = 0;
    }

    void reserve(int n) {
        if (n <= 0) return;
        n = 1 << min(23, __lg(n) + 2);
        if (cap < u32(n)) reallocate(n);
    }
};

template <typename Key, typename Data>
uint64_t HashMapBase<Key, Data>::r = chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();

}  // namespace HashMapImpl

template <typename Key, typename Val>
struct HashMap : HashMapImpl::HashMapBase<Key, pair<Key, Val>> {
    using base = typename HashMapImpl::HashMapBase<Key, pair<Key, Val>>;
    using HashMapImpl::HashMapBase<Key, pair<Key, Val>>::HashMapBase;
    using Data = pair<Key, Val>;

    Val& operator[](const Key& k) {
        typename base::u32 h = base::inner_hash(k);
        while (true) {
            if (base::occupied_flag[h] == false) {
                if (base::extend_rate(base::occupied + 1)) {
                    base::extend();
                    h = base::hash(k);
                    continue;
                }
                base::data[h].first = k;
                base::data[h].second = Val();
                base::occupied_flag[h] = true;
                ++base::occupied, ++base::s;
                return base::data[h].second;
            }
            if (base::data[h].first == k) {
                if (base::deleted_flag[h] == true) {
                    base::data[h].second = Val();
                    base::deleted_flag[h] = false;
                    ++base::s;
                }
                return base::data[h].second;
            }
            h = (h + 1) & (base::cap - 1);
        }
    }

    typename base::itr emplace(const Key& key, const Val& val) { return base::insert(Data(key, val)); }
};

template <typename Key>
struct HashSet : HashMapImpl::HashMapBase<Key, Key> {
    using HashMapImpl::HashMapBase<Key, Key>::HashMapBase;
};

constexpr int MAX = 100010;
int v[MAX], h[MAX];
ll d[MAX], accd[MAX], acch[MAX], accv[MAX];
HashMap<ll, int> dp[MAX];

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N, M;
    cin >> N >> M;
    // vector<int> v(N), h(N);
    for (int i = 0; i < N; i++) cin >> v[i] >> h[i];
    vector<int> t(M), s(M);
    for (int i = 0; i < M; i++) {
        cin >> t[i] >> s[i];
        // s[i] は実質的に単調増加列とみなせる
        if (i - 1 >= 0) s[i] = max(s[i], s[i - 1]);
    }
    // d[i] := |h[i + 1] - h[i]|
    // vector<ll> d(N - 1), accd(N), acch(N + 1), accv(N + 1);
    for (int i = 0; i + 1 < N; i++) d[i] = abs(h[i + 1] - h[i]);
    for (int i = 0; i + 1 < N; i++) accd[i + 1] = accd[i] + d[i];
    for (int i = 0; i < N; i++) {
        acch[i + 1] = acch[i] + h[i];
        accv[i + 1] = accv[i] + v[i];
    }

    // f(i, j) := [i, j) のアイテムを購入したときの強さの増分
    auto f = [&](int i, int j) -> ll { return acch[j] - acch[i] + max<ll>(0, accd[j - 1] - accd[i]); };

    // dp[i][j] := i 番目のイベント終了時,
    // 強さ j
    // のどこまでアイテムを買ったかの min
    // vector<HashMap<ll, int>> dp(M + 1);
    dp[0][0] = 0;
    for (int i = 0; i < M; i++) {
        for (auto&& [key, val] : dp[i]) {
            // 強さ key, アイテムは [0, val) まで購入
            for (int j = val + 1; j <= N; j++) {
                // [val, j) までのアイテムを購入: 強さは key + f(val, j)
                ll next_strong = key + f(val, j);
                // t[i] が [0, j) の v の総和未満なら break
                if (t[i] < accv[j]) break;
                // 次の場所まで skip (次の場所に行けない場合は continue)
                int next_event = ranges::upper_bound(s, next_strong) - s.begin();
                if (next_event <= i) continue;
                if (dp[next_event].contain(next_strong)) {
                    dp[next_event][next_strong] = min(dp[next_event][next_strong], j);
                } else {
                    dp[next_event][next_strong] = j;
                }
            }
        }
    }

    ll ans = -1;
    for (auto&& [key, val] : dp[M]) {
        // 強さ key, アイテムは [0, val) まで購入
        ans = max(ans, t[M - 1] - accv[val]);
    }

    cout << ans << '\n';
}
accuracy: 1
time_ms: 370
memory_kb: 35656
final_rank: 17

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

using VS = vector<string>;    using LL = long long;
using VI = vector<int>;       using VVI = vector<VI>;
using PII = pair<int, int>;   using PLL = pair<LL, LL>;
using VL = vector<LL>;        using VVL = vector<VL>;

#define ALL(a)  begin((a)),end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))
#define FOR(i, s, e) for (int(i) = (s); (i) < (e); (i)++)
#define FORR(i, s, e) for (int(i) = (s); (i) > (e); (i)--)
#define debug(x) cerr << #x << ": " << x << endl
const int INF = 1e9;                          const LL LINF = 1e16;
const LL MOD = 1000000007;                    const double PI = acos(-1.0);
int DX[8] = { 0, 0, 1, -1, 1, 1, -1, -1 };    int DY[8] = { 1, -1, 0, 0, 1, -1, 1, -1 };

/* -----  2018/01/15  Problem: AOJ 0344 / Link: http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0344  ----- */
/* ------問題------



-----問題ここまで----- */
/* -----解説等-----

OはDPのO

----解説ここまで---- */

LL N;

LL ans = 0LL;

int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);

	int M;

	cin >> N>>M;
	VL v(N),h(N);
	FOR(i,0,N){
		cin>>v[i]>>h[i];
	}
	VL usesum(N+1,0);
	VL powersum(N+1,0);
	FOR(i,0,N){
		usesum[i+1] += usesum[i] + v[i];
		powersum[i+1] += powersum[i] + h[i];
	}
	VL powerdiff(N+1,0);
	FOR(i,0,N-1){
		powerdiff[i] = abs(v[i] - v[i+1]);
	}
	VL powerdiffsum(N+1,0);
	FOR(i,0,N-1){
		powerdiffsum[i+1] +=powerdiffsum[i]+ powerdiff[i];
	}


	VL t(M),s(M);
	FOR(i,0,M){
		cin>>t[i]>>s[i];
	}
	vector<VVL> dp(M+1,VVL(N+1,VL(2,-1)));
	dp[0][0][0] = 0;
	// 0 simple 1 ketu
	FOR(i,0,M){
		LL nowmoney = t[i];
		FOR(j,0,N+1){
			if(dp[i][j][0]>=s[i]){
				dp[i+1][j][0] = max( dp[i+1][j][0], dp[i][j][0] );
			}
			if(dp[i][j][1]>=s[i]){
				dp[i+1][j][0] = max( dp[i+1][j][0], dp[i][j][1]);
			}
			if(j==N)continue;
			//debug(nowmoney - usesum[j+1]);
			if(nowmoney - usesum[j+1]>=0){
				if(dp[i][j][0]>=0){
					LL addpower =  h[j];
					dp[i][j+1][0] = max(dp[i][j+1][0], dp[i][j][0] + addpower);
					dp[i][j+1][1] = max(dp[i][j+1][1], dp[i][j][0] + addpower);
				}
				if(dp[i][j][1]>=0){
					LL addpower = h[j] + abs(h[j] - h[j-1]);
					dp[i][j+1][1] = max(dp[i][j+1][1],dp[i][j][1] + addpower );
				}
			}
		}
	}
 
	ans = -1;
	FOR(j,0,N+1){
		if(dp[M][j][0]!=-1){
			//debug(t[M-1]-usesum[j]);
			ans = max(ans,t[M-1] - usesum[j]);
			//debug(ans);
		}
	}
	cout<<ans<<endl;


	// VVL dp(M+1,VL(N+1),-1);
	// dp[0][0] = 0;
	// FOR(i,0,M){
	// 	FOR(j,0,N){
	// 		LL money = t[i] - usesum[j]; // time - sum[item]
	// 		LL power = dp[i][j];
	// 		FOR(k,j+1,N){ // [j+1,k]までを選択
	// 			LL cost = usesum[k+1] - usesum[j+1];
	// 			LL addpower =	powersum[k+1] - powersum[j+1] + powerdiffsum[k] -powerdiffsum[j+1]; 
	// 			if(money -cost<0)break;// cut
	// 			if(power+addpower>=s[i]){
	// 				dp[i+1][k] = max(dp[i+1][k],dp[i][j]+addpower);
	// 			}

	// 		}
	// 	}
	// }



	return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 167812
final_rank: 19

code_snippet: #include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
using ll = long long;
int main() {
  int N, M;cin >> N >> M;
  vector<ll> T(M+1, 0), S(M+1, 0), V(N+1, 0), H(N+1, 0);
  
  for (int i = 1;i <= N;i++) {
    cin >> V[i] >> H[i];
  }
  for (int i = 1;i <= M;i++) {
    cin >> T[i] >> S[i];
  }
  vector<ll> Z(N+1, 0);
  for (int i = N;i >= 1;i--) {
    Z[i] = H[i];
    if (i < N) {
      Z[i] += Z[i+1];
      Z[i] += abs(H[i]-H[i+1]);
    }
  }
  ll inf = (1LL << 60);
  vector<vector<ll>> dp(M+1, vector<ll>(N+1, -inf));
  dp[0][0] = 0;
  vector<ll> SV(N+1, 0);
  for (int i = 1;i <= N;i++) SV[i]=SV[i-1]+V[i];
  vector<ll> MX(N+1, -inf);
  vector<vector<ll>> SC(N+1, vector<ll>(N+1, 0));
 
  for (int i = 1;i <= M;i++) {
  for (int j = 1;j <= N;j++) {
    //not buy at ti
    if (dp[i-1][j] >= S[i]) {
      dp[i][j]=dp[i-1][j];
    }
    //buy at i
    if (SV[j] <= T[i]) {
      if (MX[j] != -inf) {
        ll nt = MX[j] - Z[j] + H[j];
        if (nt >= S[i]) {

          dp[i][j] = max(dp[i][j], nt);
        }
      }
    if (i == 1) {
    for (int k = 1;k <= j;k++) {
      if (dp[i-1][k-1] < 0) continue;
      ll sc = 0;
      for (int t = k;t <= j;t++) {
        sc += H[t];
        if (t < j) sc += abs(H[t]-H[t+1]);
      }
      if (dp[i-1][k-1]+sc >= S[i]) dp[i][j]=max(dp[i][j], dp[i-1][k-1] + sc);
    // cout <<  MX[j] - Z[j] + H[j] << " " << dp[i-1][k-1] + SC[k][j] << " " << i << " " << j << " " << k << endl;
     // cout << k << " " << j << " " << Z[k]-Z[j] + H[j] << " " << SC[k][j] << endl;
    }
  }
  }
  }    
    for (int k = 1;k <= N;k++) {
      MX[k]=MX[k-1];
      if (dp[i][k-1] != -inf) MX[k] = max(MX[k-1], dp[i][k-1]+Z[k]); 
    //  cout << k << " MX " << i << " " << MX[k] << endl;
    }
}
  ll res = -inf;
  for (int j = 0;j <= N;j++) {
    if (dp.back()[j] != -inf) {
      res = max(res, T.back() - SV[j]);
    }
  }
  cout << (res < 0 ? -1 : res) << endl;
}
accuracy: 1
time_ms: 30
memory_kb: 97408
final_rank: 16

code_snippet: // AOJ #344
// Game Strategy 202.2.8

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll NEG = -1000000000000000000LL;

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    int N, M;
    cin >> N >> M;
    vector<ll> v(N+1), h(N+1);
    for (int i = 1; i <= N; i++){
        cin >> v[i] >> h[i];
    }

    vector<ll> V(N+1,0), H(N+1,0);
    for (int i = 1; i <= N; i++){
        V[i] = V[i-1] + v[i];
        H[i] = H[i-1] + h[i];
    }

    vector<ll> D(N+1, 0);
    D[1] = 0;
    for (int i = 2; i <= N; i++){
        D[i] = D[i-1] + llabs(h[i] - h[i-1]);
    }
 
    vector<ll> T(M+1), Sreq(M+1);
    for (int i = 1; i <= M; i++){
        cin >> T[i] >> Sreq[i];
    }
 

    vector<ll> dp(N+1, NEG), next_dp(N+1, NEG);
    dp[0] = 0;
 
    for (int evt = 1; evt <= M; evt++){
        for (int j = 0; j <= N; j++) next_dp[j] = NEG;
 
        for (int j = 0; j <= N; j++){
            if(dp[j] != NEG && dp[j] >= Sreq[evt]){
                next_dp[j] = max(next_dp[j], dp[j]);
            }
        }

        vector<ll> best(N, NEG);
        best[0] = dp[0] - 0 - ( (1<=N ? D[1] : 0) );
        for (int j = 1; j < N; j++){
            ll candidate = dp[j] - H[j] - D[j+1];
            best[j] = max(best[j-1], candidate);
        }
 
        for (int k = 1; k <= N; k++){
            if(V[k] <= T[evt]){
                ll candidate = best[k-1] + (H[k] + D[k]);
                if(candidate >= Sreq[evt]){
                    next_dp[k] = max(next_dp[k], candidate);
                }
            }
        }
 
        dp = next_dp;
    }
 
    ll ans = NEG;
    bool possible = false;
    for (int j = 0; j <= N; j++){
        if(dp[j] != NEG){
            ll money = T[M] - V[j];
            ans = max(ans, money);
            possible = true;
        }
    }
    if(!possible) cout << -1 << endl;
    else cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3600
final_rank: 4

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

int main()
{
	long long n,m;
	cin >> n >> m;
	vector<pair<long long,long long>> a(n),b(m);
	vector<long long> p(n,0ll);
	for(long long i = 0ll;i < n;i++){
		cin >> a[i].first >> a[i].second;
		if(i != 0ll){
			p[i - 1ll] = abs(a[i].second - a[i - 1ll].second);
		}
	}
	for(long long i = 0ll;i < n;i++){
		a[i].second += p[i];
		if(i != 0ll){
			a[i].second += a[i - 1ll].second;
			a[i].first += a[i - 1ll].first;
		}
	}
	for(long long i = 0ll;i < m;i++){
		cin >> b[i].first >> b[i].second;
	}
	vector<vector<long long>> dp(m + 1ll,vector<long long>(n + 1ll,LLONG_MAX));
	dp[0ll][0ll] = 0ll;
	for(long long i = 0ll;i < m;i++){
		long long it = LLONG_MAX;
		for(long long j = 1ll;j <= n;j++){
			it = min(it,dp[i][j - 1ll]);
			if(a[j - 1ll].second - dp[i][j] >= b[i].second){
				dp[i + 1ll][j] = min(dp[i][j],dp[i + 1ll][j]);
			}
			if(it != LLONG_MAX && a[j - 1ll].first <= b[i].first && a[j - 1ll].second - it - p[j - 1ll] >= b[i].second){
				dp[i + 1ll][j] = min(it + p[j - 1ll],dp[i + 1ll][j]);
			}
		}
	}
	long long ans = -1ll;
	for(long long i = 1ll;i <= n;i++){
		if(dp[m][i] == LLONG_MAX) continue;
		ans = max(ans,b[m - 1ll].first - a[i - 1ll].first);
	}
	cout << ans << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 26616
final_rank: 7

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

int main() {
  int N, M;
  cin >> N >> M;
  vector<int> v(N), h(N);
  for(int i = 0; i < N; i++) {
    cin >> v[i] >> h[i];
  }
  vector<int> t(M), s(M);
  for(int i = 0; i < M; i++) {
    cin >> t[i] >> s[i];
  }
  if(v[0] > t[0]) {
    cout << -1 << endl;
    return 0;
  }
  const int INF = 800000000;
  vector<int> dp(N, -INF), ep(N, -INF);
  { // init
    dp[0] = h[0];
    int sv = v[0];
    for(int i = 1; i < N; i++) {
      sv += v[i];
      if(sv > t[0]) break;
      dp[i] = dp[i-1]+h[i]+abs(h[i-1]-h[i]);
    }
    for(int i = 0; i < N; i++) {
      if(dp[i] < s[0]) dp[i] = -INF;
    }
  }
  for(int j = 1; j < M; j++) {
    int fi = -1;
    for(int i = 0; i < N; i++) {
      if(dp[i] != -INF) {
        fi = i;
        break;
      }
    }
    if(fi == -1) {
      cout << -1 << endl;
      return 0;
    }
    int sv = 0, mep = -INF;
    for(int i = 0; i < N; i++) {
      sv += v[i];
      if(i < fi) continue;
      if(sv > t[j]) break;
      ep[i] = dp[i];
      if(i > 0) ep[i] = max({dp[i], dp[i-1]+h[i], mep+h[i]+abs(h[i]-h[i-1])});
      if(i > fi) mep = max(mep+h[i]+abs(h[i-1]-h[i]), dp[i-1]+h[i]);
    }
    for(int i = 0; i < N; i++) {
      if(ep[i] < s[j]) ep[i] = -INF;
    }
    swap(dp, ep);
    fill(ep.begin(), ep.end(), -INF);
  }
  int sv = 0;
  for(int i = 0; i < N; i++) {
    sv += v[i];
    if(dp[i] != -INF) {
      cout << t[M-1]-sv << endl;
      return 0;
    }
  }
  cout << -1 << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3436
final_rank: 2

code_snippet: /* -*- coding: utf-8 -*-
 *
 * 0344.cc: Game Strategy
 */

#include<cstdio>
#include<algorithm>
 
using namespace std;

/* constant */

const int MAX_N = 3000;
const int MAX_M = 1000;
const int INF = 1 << 30;

/* typedef */

/* global variables */

int vs[MAX_N], hs[MAX_N], ts[MAX_M + 1], ss[MAX_M];
int vss[MAX_N + 1], dp[MAX_M + 1][MAX_N + 1][2];

/* subroutines */

void setmax(int &a, int b) { if (a < b) a = b; }

/* main */

int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  for (int i = 0; i < n; i++) scanf("%d%d", vs + i, hs + i);
  for (int i = 0; i < m; i++) scanf("%d%d", ts + i, ss + i);
  ts[m] = INF;

  for (int i = 0; i < n; i++) vss[i + 1] = vss[i] + vs[i];

  for (int i = 0; i <= m; i++)
    for (int j = 0; j <= n; j++) dp[i][j][0] = dp[i][j][1] = -1;
  dp[0][0][0] = 0;

  for (int i = 0; i <= m; i++)
    for (int j = 0; j <= n; j++)
      for (int k = 0; k < 2; k++)
	if (dp[i][j][k] >= 0) {
	  if (i < m && dp[i][j][k] >= ss[i])
	    setmax(dp[i + 1][j][0], dp[i][j][k]);
	  if (j < n && ts[i] >= vss[j + 1]) {
	    int dd = hs[j] + (k == 1 ? abs(hs[j] - hs[j - 1]) : 0);
	    setmax(dp[i][j + 1][1], dp[i][j][k] + dd);
	  }
	}

  int minj = INF;
  for (int j = 0; j <= n; j++)
    if (dp[m][j][0] >= 0 || dp[m][j][1] >= 0) {
      minj = j; break;
    }

  printf("%d\n", (minj < INF) ? ts[m - 1] - vss[minj] : -1);
  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 26464
final_rank: 8

code_snippet: //#pragma GCC target ("avx2")
//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define _USE_MATH_DEFINES
#include<iostream>
#include<string>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#include<list>
#include<iomanip>
#include<vector>
#include<random>
#include<functional>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<cstring>
#include<bitset>
#include<unordered_map>
#include<climits>
#include<fstream>
#include<complex>
#include<time.h>
#include<cassert>
#include<functional>
#include<numeric>
#include<tuple>
using namespace std;
using ll = long long;
using ld = long double;
using H = pair<ll, ll>;
using P = pair<ll, H>;
using vi = vector<ll>;
#define all(a) (a).begin(),(a).end()
#define fs first
#define sc second
#define xx first
#define yy second.first
#define zz second.second
#define Q(i,j,k) mkp((i),mkp((j),(k)))
#define rng(i,s,n) for(ll i = (s) ; i < (n) ; i++)
#define rep(i,n) rng(i, 0, (n))
#define mkp make_pair
#define vec vector
#define pb emplace_back
#define siz(a) int((a).size())
#define crdcomp(b) sort(all((b)));(b).erase(unique(all((b))),(b).end())
#define getidx(b,i) (lower_bound(all((b)),(i))-(b).begin())
#define ssp(i,n) (i==(ll)(n)-1?"\n":" ")
#define ctoi(c) (int)((c)-'0')
#define itoc(c) (char)((c)+'0')
#define cyes printf("Yes\n")
#define cno printf("No\n")
#define cdf(n) for(int quetimes_=(n);quetimes_>0;quetimes_--)
#define gcj printf("Case #%lld: ",quetimes_+1)
#define readv(a,n) (a).resize((n),0);rep(i,(n)) (a)[i]=read()
#define found(a,x) (a.find(x)!=a.end())
constexpr ll mod = (ll)1e9 + 7;
constexpr ll Mod = 998244353;
constexpr ld EPS = 1e-10;
constexpr ll inf = (ll)3 * 1e18;
constexpr int Inf = (ll)15 * 1e8;
constexpr int dx[] = { -1,1,0,0 }, dy[] = { 0,0,-1,1 };
template<class T>bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }
ll read() { ll u, k = scanf("%lld", &u); return u; }
string reads() { string s; cin >> s; return s; }
H readh(short g = 0) { H u; int k = scanf("%lld %lld", &u.fs, &u.sc); if (g == 1) u.fs--, u.sc--; if (g == 2) u.fs--; return u; }
bool ina(H t, int h, int w) { return 0 <= t.fs && t.fs < h && 0 <= t.sc && t.sc < w; }
bool ina(int t, int l, int r) { return l <= t && t < r; }
ll gcd(ll i, ll j) { return j ? gcd(j, i % j) : i; }
ll ppc(ll x) {
    int sum = 0; for (int i = 0; i < 60; i++)if ((1ll << i) & x) sum++;
    return sum;
}
template<typename T>
void fin(T x) { cout << x << endl; exit(0); }

template<typename T>
class csum {
    vec<T> v;
public:
    csum(vec<T>& a) :v(a) { build(); }
    csum() {}
    csum(int sz) { init(sz); }
    void init(int sz) { v = vector<T>(sz + 1, 0); }
    void init(vec<T>& a) { v = a; build(); }
    void build() {
        for (int i = 1; i < v.size(); i++) v[i] += v[i - 1];
    }
    void add(int l, int r, T x) {
        v[l] += x;
        v[r] -= x;
    }//[l,r)
    void add(int t, T x) {
        v[t] += x;
    }//[l,r)
    //[l,r]
    T a(int l, int r) {
        if (r < l) return 0;
        return v[r] - (l == 0 ? 0 : v[l - 1]);
    }
    //[l,r)
    T b(int l, int r) {
        return a(l, r - 1);
    }
    T a(pair<int, int>t) {
        return a(t.first, t.second);
    }
    T b(pair<int, int>t) {
        return b(t.first, t.second);
    }
    T operator[](int x)const {
        return v[x];
    }
};
class via {
    using H = pair<ll, ll>;
    bool comp;
public:
    vector<H>a;
    via() :comp(true) {}
    via(vector<H>dat) :a(dat), comp(false) { build(); }
    void push(int l, int r) { a.push_back(H{ l,r }); comp = false; }
    void push(H a) { push(a.first, a.second); }
    void build() {
        if (comp) return;
        comp = true;
        sort(a.begin(), a.end());
        int fst = -1; ll lst = -1;
        vector<H>b;
        for (int i = 0; i < a.size(); i++) {
            if (fst < 0) fst = i, lst = a[i].second;
            if (lst < a[i].first) {
                b.push_back(H{ a[fst].first,lst });
                fst = i, lst = a[i].second;
            }
            else if (lst < a[i].second) lst = a[i].second;
        }
        if (~fst) b.push_back(H{ a[fst].first, lst });
        a = b;
    }
    ll size() { return ll(a.size()); }
    ll sum() {
        build();
        ll sum = 0;
        for (auto g : a) sum += g.second - g.first;
        return sum;
    }
    via inter(via& v) {
        build(); v.build();
        via ret;
        for (auto g : a) ret.push(g);
        for (auto g : v.a) ret.push(g);
        ret.build(); return ret;
    }
    via comb(via& v) {
        build(); v.build();
        int s = 0, t = 0;
        via ret;
        while (s < a.size() && t < v.size()) {
            if (v[t].second <= a[s].first)  t++;
            else if (a[s].second <= v[t].first) s++;
            else {
                ret.push(max(a[s].first, v[t].first), min(a[s].second, v[t].second));
                if (a[s].second <= v[t].second) s++;
                else t++;
            }
        }
        return ret;
    }
    H& operator[](int t) { return a[t]; }
};
template<ll mod>
class modint {
public:ll v;
      modint(ll v = 0) { s(v % mod + mod); }
      constexpr static int fn_ = (ll)2e6 + 5;
      static vector<modint>fact, comp;
      modint pow(ll x) const {
          modint b(v), c(1);
          while (x) {
              if (x & 1) c *= b;
              b *= b;
              x >>= 1;
          }
          return c;
      }
      inline modint& s(int vv) {
          v = vv < mod ? vv : vv - mod;
          return *this;
      }
      inline modint inv()const { return pow(mod - 2); }
      inline modint operator-()const { return modint() - *this; }
      inline modint& operator+=(const modint b) { return s(v + b.v); }
      inline modint& operator-=(const modint b) { return s(v + mod - b.v); }
      inline modint& operator*=(const modint b) { v = v * b.v % mod; return *this; }
      inline modint& operator/=(const modint b) { v = v * b.inv().v % mod; return *this; }
      inline modint operator+(const modint& b) const { return modint(v) += b; }
      inline modint operator-(const modint& b) const { return modint(v) -= b; }
      inline modint operator*(const modint& b) const { return modint(v) *= b; }
      inline modint operator/(const modint& b) const { return modint(v) /= b; }
      friend ostream& operator<<(ostream& os, const modint& m) {
          return os << m.v;
      }
      friend istream& operator>>(istream& is, modint& m) {
          int x; is >> x; m = modint(x);
          return is;
      }
      bool operator<(const modint& r)const { return v < r.v; }
      bool operator>(const modint& r)const { return v > r.v; }
      bool operator<=(const modint& r)const { return v <= r.v; }
      bool operator>=(const modint& r)const { return v >= r.v; }
      bool operator==(const modint& r)const { return v == r.v; }
      bool operator!=(const modint& r)const { return v != r.v; }
      explicit operator bool()const { return v; }
      explicit operator int()const { return v; }
      modint comb(modint k) {
          if (k > *this) return modint();
          if (fact.empty()) combinit();
          if (v >= fn_) {
              if (k > *this - k) k = *this - k;
              modint tmp(1);
              for (int i = v; i >= v - k.v + 1; i--) tmp *= modint(i);
              return tmp * comp[k.v];
          }
          return fact[v] * comp[k.v] * comp[v - k.v];
      }//nCk
      modint perm(modint k) {
          if (k > *this) return modint();
          if (fact.empty()) combinit();
          if (v >= fn_) {
              modint tmp(1);
              for (int i = v; i >= v - k.v + 1; i--) tmp *= modint(i);
              return tmp;
          }
          return fact[v] * comp[v - k.v];
      }//nPk
      static void combinit() {
          fact.assign(fn_, modint());
          fact[0] = 1;
          for (int i = 1; i < fn_; i++) fact[i] = fact[i - 1] * modint(i);
          comp.assign(fn_, modint());
          comp[fn_ - 1] = fact[fn_ - 1].inv();
          for (int i = fn_ - 2; i >= 0; i--) comp[i] = comp[i + 1] * modint(i + 1);
      }
};
using mint = modint<ll(1e9 + 7)>; template<>vec<mint> mint::fact = vec<mint>(); template<>vec<mint> mint::comp = vec<mint>();
//--------------------------------------------------------------
//--------------------------------------------------------------
template<class T>
class LazySegmentTree {
protected:
    using UPF = function<void(T&, const int&)>;
    using QRF = function<void(T&, const T)>;
    using F = function<bool(T a)>;
    using ll = long long;
    int n, rr;
    vector<T>dat;
    vector<int>len;

    LazySegmentTree() {}
    LazySegmentTree(int size) { init(size); }
    LazySegmentTree(vector<T>& v) {
        init(v);
    }
    virtual ~LazySegmentTree() {}

    virtual void eval(const T& par, T& a, const int& al) = 0;
    virtual void fold(T& par, const int& pl) = 0;
    virtual T proc(const T& a, const int& al, const T& b, const int& bl) = 0;

public:
    void init(int size) {
        n = size, rr = 1;
        while (rr < n) rr <<= 1;
        dat.assign(2 * rr - 1, T());
        len.assign(2 * rr - 1, 0);
        for (int i = 0; i < n; i++) {
            len[i + rr - 1] = 1;
            dat[i + rr - 1] = T();
        }
        for (int i = rr - 2; i >= 0; i--) {
            len[i] = len[i * 2 + 1] + len[i * 2 + 2];
            dat[i] = proc(dat[i * 2 + 1], len[i * 2 + 1], dat[i * 2 + 2], len[i * 2 + 2]);
        }
    }
    void init(vector<T>& v) {
        n = (int)v.size(), rr = 1;
        while (rr < n) rr <<= 1;
        dat.assign(2 * rr - 1, T());
        len.assign(2 * rr - 1, 0);
        for (int i = 0; i < n; i++) {
            dat[i + rr - 1] = v[i];
            len[i + rr - 1] = 1;
        }
        for (int i = rr - 2; i >= 0; i--) {
            len[i] = len[i * 2 + 1] + len[i * 2 + 2];
            dat[i] = proc(dat[i * 2 + 1], len[i * 2 + 1], dat[i * 2 + 2], len[i * 2 + 2]);
        }
    }
    void upd(int a, int b, UPF func) {
        upd(0, a, b, 0, rr, func);
    }
    T qry(int a, int b) {
        return qry(0, a, b, 0, rr);
    }
    T get0() {
        return dat[0];
    }
    //func([a,i))==true, func([a,i+1))==false
    int lb(int a, int b, F func) {
        T e = T();
        int lgt = 0;
        return lb(0, a, b, 0, rr, func, e, lgt);
    }
    //func([i,b))==true, func([i-1,b))==false
    int ub(int a, int b, F func) {
        T e = T();
        int lgt = 0;
        return ub(0, a, b, 0, rr, func, e, lgt);
    }
private:
    void upd(int i, const int& a, const int& b, int l, int r, UPF& func) {
        if (b <= l || r <= a) return;
        if (a <= l && r <= b) {
            func(dat[i], len[i]);
            return;
        }
        eval(dat[i], dat[i * 2 + 1], len[i * 2 + 1]);
        eval(dat[i], dat[i * 2 + 2], len[i * 2 + 2]);
        fold(dat[i], len[i]);

        upd(i * 2 + 1, a, b, l, (l + r) / 2, func);
        upd(i * 2 + 2, a, b, (l + r) / 2, r, func);

        dat[i] = proc(dat[i * 2 + 1], len[i * 2 + 1], dat[i * 2 + 2], len[i * 2 + 2]);
    }
    T qry(int i, const int& a, const int& b, int l, int r) {
        if (b <= l || r <= a) return T();
        if (a <= l && r <= b) return dat[i];

        eval(dat[i], dat[i * 2 + 1], len[i * 2 + 1]);
        eval(dat[i], dat[i * 2 + 2], len[i * 2 + 2]);
        fold(dat[i], len[i]);

        return proc(qry(i * 2 + 1, a, b, l, (l + r) / 2), len[i * 2 + 1],
            qry(i * 2 + 2, a, b, (l + r) / 2, r), len[i * 2 + 2]);
    }
    int lb(int i, int a, int b, int l, int r, F& func, T& wa, int& lgt) {
        if (b <= l || r <= a) return b;
        if (a <= l && r <= b) {
            if (func(proc(wa, lgt, dat[i], len[i]))) {
                wa = proc(wa, lgt, dat[i], len[i]);
                lgt += len[i];
                return b;
            }
            if (r - l == 1) return l;
        }
        eval(dat[i], dat[i * 2 + 1], len[i * 2 + 1]);
        eval(dat[i], dat[i * 2 + 2], len[i * 2 + 2]);
        fold(dat[i], len[i]);

        int tmp = lb(i * 2 + 1, a, b, l, (l + r) / 2, func, wa, lgt);
        if (tmp < b) return tmp;
        return lb(i * 2 + 2, a, b, (l + r) / 2, r, func, wa, lgt);
    }
    int ub(int i, int a, int b, int l, int r, F& func, T& wa, int& lgt) {
        if (b <= l || r <= a) return a;
        if (a <= l && r <= b) {
            if (func(proc(dat[i], len[i], wa, lgt))) {
                wa = proc(dat[i], len[i], wa, lgt);
                lgt += len[i];
                return a;
            }
            if (r - l == 1) return r;
        }
        eval(dat[i], dat[i * 2 + 1], len[i * 2 + 1]);
        eval(dat[i], dat[i * 2 + 2], len[i * 2 + 2]);
        fold(dat[i], len[i]);

        int tmp = ub(i * 2 + 2, a, b, (l + r) / 2, r, func, wa, lgt);
        if (tmp > a) return tmp;
        return ub(i * 2 + 1, a, b, l, (l + r) / 2, func, wa, lgt);
    }
};
template<class T>
class Segtree :public LazySegmentTree<T> {
    using Base = LazySegmentTree<T>;
public:
    Segtree() {}
    Segtree(int size) {
        init(size);
    }
    Segtree(vector<ll>& v) {
        init(v);
    }
    Segtree(vector<T>& v) { init(v); }
    void init(int size) {
        Base::init(size);
    }
    void init(vector<ll>& v) {
        vector<T>r(v.size());
        for (int i = 0; i < v.size(); i++) r[i] = T{ v[i],0 };
        Base::init(r);
    }
    void init(vector<T>& v) {
        Base::init(v);
    }

    void change(int p, ll x) {
        Base::upd(p, p + 1, [x](T& dat, const int& len) {
            dat.val = x; dat.lazy = 0;
            });
    }
    void update(int a, int b, ll x) {
        Base::upd(a, b, [x](T& dat, const int& len) {
            dat.val += x; dat.lazy = x;
            });
    }
    ll query(int a, int b) {
        return Base::qry(a, b).val;
    }
    ll get0() {
        return Base::get0().val;
    }
private:
    void eval(const T& par, T& a, const int& al)override {
        if (par.lazy) {
            a.val += par.lazy;
            a.lazy += par.lazy;
        }
    }
    void fold(T& par, const int& pl) override {
        par.lazy = 0;
    }
    T proc(const T& a, const int& al, const T& b, const int& bl)override {
        return T{ max(a.val, b.val) ,0 };
    }
};
struct Monoid {
    ll val; ll lazy;
    Monoid() :val(-inf), lazy(0) {}
    Monoid(ll val, ll lazy) :val(val), lazy(lazy) {}
};

ll dp[4000][2000];
signed main() {
    int n, m; cin >> n >> m;
    vec<H>a(n+1), b(m + 1);
    for (int i = 0; i < n; i++) {
        a[i] = readh();
    }
    rep(i, m) b[i] = readh();
    Segtree<Monoid>seg(n + 1);
    seg.change(0, 0);


    vi dp(n + 1);
    rep(i, m) {
        ll sum = 0;
        dp = vi(n + 1);
        rng(j, 0, n) {
            sum += a[j].fs;
            if (sum > b[i].fs) break;

            seg.update(0, j + 1, a[j].sc);
            if (j > 0) seg.update(0, j, abs(a[j - 1].sc - a[j].sc));

            dp[j + 1] = seg.query(0, j + 2);
        }
        rep(j, n + 1) if (dp[j] < b[i].sc) dp[j] = -inf;
        seg.init(dp);
    }

    ll sum = b[m - 1].fs;
    rep(i, n + 1) {
        if (dp[i] > 0) {
            fin(sum);
        }
        if (i < n) sum -= a[i].fs;
    }
    cout << -1 << endl;
}
accuracy: 1
time_ms: 850
memory_kb: 3840
final_rank: 18

code_snippet: #include<iostream>
#include<algorithm>
using namespace std;
int N,M;
int v[3000],h[3000];
int sv[3030];
int t[1000],s[1000];
int dp[1010][3030];
main()
{
	cin>>N>>M;
	for(int i=0;i<N;i++)
	{
		cin>>v[i]>>h[i];
		sv[i+1]=sv[i]+v[i];
	}
	for(int i=0;i<M;i++)cin>>t[i]>>s[i];
	for(int i=0;i<=M;i++)for(int j=0;j<=N;j++)dp[i][j]=-1e9;
	dp[0][0]=0;
	for(int i=0;i<M;i++)
	{
		int mx1=-1e9,mx2=dp[i][0];
		for(int j=1;j<=N;j++)if(sv[j]<=t[i])
		{
			if(j>1)mx1+=abs(h[j-1]-h[j-2]);
			mx1+=h[j-1];
			mx2+=h[j-1];
			mx1=max(mx1,mx2);
			mx2=max(mx2,dp[i][j]);
			dp[i][j]=max(mx1,mx2);
		}
		for(int j=0;j<=N;j++)if(dp[i][j]>=s[i])dp[i+1][j]=dp[i][j];
	}
	int ans=-1;
	for(int j=0;j<=N;j++)if(dp[M][j]>=0)ans=max(ans,t[M-1]-sv[j]);
	cout<<ans<<endl;
}
accuracy: 1
time_ms: 10
memory_kb: 15004
final_rank: 5

code_snippet: #include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
const int inf = 1012345678;
int solve(int N, int M, vector<int> V, vector<int> H, vector<int> T, vector<int> S) {
	V.insert(V.begin(), 0);
	for (int i = 0; i < N; ++i) {
		V[i + 1] += V[i];
	}
	for (int i = 1; i < M; ++i) {
		S[i] = max(S[i], S[i - 1]);
	}
	vector<int> dp(N + 1, -inf); // maintain maximum strength
	dp[0] = 0;
	for (int i = 1; i <= N; ++i) {
		int ptr = lower_bound(T.begin(), T.end(), V[i]) - T.begin() - 1;
		int delta = 0;
		for (int j = i - 1; j >= 0; --j) {
			delta += H[j];
			if (j != i - 1) {
				delta += abs(H[j] - H[j + 1]);
			}
			if (ptr == -1 || S[ptr] <= dp[j]) {
				dp[i] = max(dp[i], dp[j] + delta);
			}
		}
	}
	int ans = -inf;
	for (int i = 0; i <= N; ++i) {
		if (dp[i] >= S[M - 1]) {
			ans = max(ans, T[M - 1] - V[i]);
		}
	}
	return (ans != -inf ? ans : -1);
}
int solve_easy(int N, int M, vector<int> V, vector<int> H, vector<int> T, vector<int> S) {
	int ans = -inf;
	for (int i = 0; i < 1 << N; ++i) {
		vector<pair<int, int> > d = { make_pair(0, 0) };
		int cont = 0, strength = 0, t = 0;
		for (int j = 0; j < N; ++j) {
			++cont;
			strength += H[j];
			if (cont >= 2) strength += abs(H[j] - H[j - 1]);
			t += V[j];
			if ((i >> j) & 1) {
				d.push_back(make_pair(t, strength));
				cont = 0;
			}
		}
		bool ok = true;
		for (int j = 0; j < M; ++j) {
			int ptr = lower_bound(d.begin(), d.end(), make_pair(T[j] + 1, -inf)) - d.begin() - 1;
			if (d[ptr].second < S[j]) {
				ok = false;
				break;
			}
		}
		if (ok) {
			ans = max(ans, T.back() - d.back().first);
		}
	}
	return (ans != -inf ? ans : -1);
}
#include <random>
#include <string>
mt19937 mt(2009092038);
int rand_rng(int l, int r) {
	uniform_int_distribution<int> p(l, r - 1);
	return p(mt);
}
string to_string(vector<int> arr) {
	string res = "[";
	for (int i = 0; i < arr.size(); ++i) {
		if (i) res += ", ";
		res += to_string(arr[i]);
	}
	res += "]";
	return res;
}
void random_gen() {
	const int rep = 10000;
	int N = 7, M = 7;
	for (int i = 1; i <= rep; ++i) {
		vector<int> V(N), H(N), T(M), S(M);
		for (int j = 0; j < N; ++j) {
			V[j] = rand_rng(1, 8);
			H[j] = rand_rng(1, 8);
		}
		for (int j = 0; j < M; ++j) {
			T[j] = rand_rng(1, 40);
			S[j] = rand_rng(1, 40);
		}
		sort(T.begin(), T.end());
		for (int j = 0; j < M; ++j) {
			T[j] += j;
		}
		int res1 = solve(N, M, V, H, T, S);
		int res2 = solve_easy(N, M, V, H, T, S);
		if (res1 != res2) {
			cout << "Case #" << i << ":" << endl;
			cout << "V = " << to_string(V) << endl;
			cout << "H = " << to_string(H) << endl;
			cout << "T = " << to_string(T) << endl;
			cout << "S = " << to_string(S) << endl;
			cout << "Returns: " << res1 << endl;
			cout << "Answer: " << res2 << endl;
			cout << endl;
		}
	}
	cout << "Finished!" << endl;
}
int main() {
	// random_gen();
	cin.tie(0);
	ios_base::sync_with_stdio(false);
	int N, M;
	cin >> N >> M;
	vector<int> V(N), H(N), T(M), S(M);
	for (int i = 0; i < N; ++i) {
		cin >> V[i] >> H[i];
	}
	for (int i = 0; i < M; ++i) {
		cin >> T[i] >> S[i];
	}
	int res = solve(N, M, V, H, T, S);
	cout << res << endl;
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3332
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using VI = vector<int>;
using VL = vector<ll>;
using VS = vector<string>;
template<class T> using PQ = priority_queue<T, vector<T>, greater<T>>;
#define FOR(i,a,n) for(int i=(a);i<(n);++i)
#define eFOR(i,a,n) for(int i=(a);i<=(n);++i)
#define rFOR(i,a,n) for(int i=(n)-1;i>=(a);--i)
#define erFOR(i,a,n) for(int i=(n);i>=(a);--i)
#define each(i, a) for(auto &i : a)
#define SORT(a) sort(a.begin(),a.end())
#define rSORT(a) sort(a.rbegin(),a.rend())
#define fSORT(a,f) sort(a.begin(),a.end(),f)
#define all(a) a.begin(),a.end()
#define out(y,x) ((y)<0||h<=(y)||(x)<0||w<=(x))
#define tp(a,i) get<i>(a)
#define line cout << "-----------------------------\n" 
#define ENDL(i,n) ((i) == (n) - 1 ? "\n" : " ")
#define elif else if
constexpr ll INF = 1000000000;
constexpr ll LLINF = 1LL << 60;
constexpr ll mod = 1000000007;
constexpr ll MOD = 998244353;
constexpr ld eps = 1e-10;
constexpr ld pi = 3.1415926535897932;
template<class T>inline bool chmax(T& a, const T& b) { if (a < b) { a = b; return true; }return false; }
template<class T>inline bool chmin(T& a, const T& b) { if (a > b) { a = b; return true; }return false; }
inline void init() { cin.tie(nullptr); cout.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(15); }
template<class T>inline istream& operator>>(istream& is, vector<T>& v) { for (auto& a : v)is >> a; return is; }
template<class T>inline istream& operator>>(istream& is, deque<T>& v) { for (auto& a : v)is >> a; return is; }
template<class T, class U>inline istream& operator>>(istream& is, pair<T, U>& p) { is >> p.first >> p.second; return is; }
template<class T>inline vector<T> vec(size_t a) { return vector<T>(a); }
template<class T>inline vector<T> defvec(T def, size_t a) { return vector<T>(a, def); }
template<class T, class... Ts>inline auto vec(size_t a, Ts... ts) { return vector<decltype(vec<T>(ts...))>(a, vec<T>(ts...)); }
template<class T, class... Ts>inline auto defvec(T def, size_t a, Ts... ts) { return vector<decltype(defvec<T>(def, ts...))>(a, defvec<T>(def, ts...)); }
template<class T>inline void print(const T& a) { cout << a << "\n"; }
template<class T, class... Ts>inline void print(const T& a, const Ts&... ts) { cout << a << " "; print(ts...); }
template<class T>inline void print(const vector<T>& v) { for (int i = 0; i < v.size(); ++i)cout << v[i] << (i == v.size() - 1 ? "\n" : " "); }
template<class T>inline void print(const vector<vector<T>>& v) { for (auto& a : v)print(a); }
inline string reversed(const string& s) { string t = s; reverse(all(t)); return t; }

template<class Op> class SegmentTree {
    using T = typename Op::T;
    int len, n;
    vector<T> dat;
    T unit = Op::unit;
public:
    SegmentTree(const int _n) : n(_n) {
        for (len = 1; len < n; len <<= 1);
        dat.resize(len << 1, unit);
    }
    SegmentTree(const vector<T>& v) : n(v.size()) {
        for (len = 1; len < n; len <<= 1);
        dat.resize(len << 1, unit);
        for (int i = 0; i < n; ++i)dat[i + len] = v[i];
        for (int i = len - 1; 0 < i; --i)
            dat[i] = Op::merge(dat[i << 1], dat[i << 1 | 1]);
    }
    inline void update(int idx, const T a) {
        idx += len;
        dat[idx] = Op::update(dat[idx], a);
        for (idx >>= 1; 0 < idx; idx >>= 1)
            dat[idx] = Op::merge(dat[idx << 1], dat[idx << 1 | 1]);
    }
    inline T value(int l, int r) {
        T vl = unit, vr = unit;
        for (l += len, r += len; l < r; l >>= 1, r >>= 1) {
            if (l & 1)vl = Op::merge(vl, dat[l++]);
            if (r & 1)vr = Op::merge(dat[--r], vr);
        }
        return Op::merge(vl, vr);
    }
    inline T operator[](int idx) { return dat[idx + len]; }
};
template<class Type> struct llMaxChmaxUpdate {
    using T = Type;
    const static T unit = -1;
    inline static T merge(T vl, T vr) { return max(vl, vr); }
    inline static T update(T vl, T vr) { return max(vl, vr); }
};

int main() {
    init();

    int n, m; cin >> n >> m;
    VL v(n + 1), h(n + 1);
    FOR(i, 0, n)cin >> v[i] >> h[i];
    VL d(n + 1);
    FOR(i, 0, n - 1) {
        d[i] += abs(h[i + 1] - h[i]);
        d[i + 1] += d[i];
    }
    FOR(i, 0, n - 1) {
        v[i + 1] += v[i];
        h[i + 1] += h[i];
    }

    auto val = [&](int l, int r) { //[l,r]
        chmax(l, 0);
        if (l > r)return 0LL;
        return h[r] - (l == 0 ? 0 : h[l - 1])
            + (r == 0 ? 0 : d[r - 1]) - (l == 0 ? 0 : d[l - 1]);
    };

    VL t(m), s(m);
    FOR(i, 0, m)cin >> t[i] >> s[i];
    SegmentTree<llMaxChmaxUpdate<ll>> seg1(VL(n + 1, -1));
    seg1.update(0, val(0, n - 1));

    VI l(m + 1, INF), r(m + 1, -1);
    l[0] = r[0] = 0;
    ll ans = -1;
    FOR(i, 0, m) {
        ll res;
        SegmentTree<llMaxChmaxUpdate<ll>> seg2(VL(n + 1, -1));
        eFOR(j, l[i], n) {
            if (t[i] < (j == 0 ? 0 : v[j - 1]))break;
            res = max(seg1.value(l[i], min(r[i] + 1, j))
                - val(j - 1, n - 1) + val(j - 1, j - 1), seg1[j] - val(j, n - 1));
            if (s[i] <= res) {
                chmin(l[i + 1], j);
                chmax(r[i + 1], j);
                seg2.update(j, res + val(j, n - 1));
                if (i == m - 1)
                    chmax(ans, t[m - 1] - (j == 0 ? 0 : v[j - 1]));
            }
        }
        seg1 = seg2;
    }
    print(ans);

    return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 3324
final_rank: 9

code_snippet: #include<iostream>
#include<vector>
#include<utility>
#include<algorithm>
using namespace std;
int main() {
	long long N,M;
	cin >> N >> M;
	vector<long long> h(2*N,0),v(N+1,0),t(M),s(M);
	long long i,j,k;
	for(i=0;i<N;i++) {
		cin >> j;
		v[i+1] = v[i] + j;
		cin >> j;
		if(i>0)h[2*i] = h[2*i-1]+abs(j-(h[2*i-1]-h[2*i-2]));
		h[2*i+1] = h[2*i] + j;
	}
	for(i=0;i<M;i++)cin >> t[i] >> s[i];
	vector<vector<long long>> dp(M+1,vector<long long>(N+1,-1));
	dp[0][0] = 0;
	long long l,r;
	bool f;
	vector<vector<pair<pair<long long,long long>,long long>>> a(2,vector<pair<pair<long long,long long>,long long>>(1,pair<pair<long long,long long>,long long>(pair<long long,long long>(h[2*N-1]-h[0],0),0)));
	vector<bool> ed(N);
	for(i=0;i<M;i++) {
		vector<pair<pair<long long,long long>,long long>>().swap(a[(i+1)%2]);
		sort(a[i%2].begin(),a[i%2].end(),greater<pair<pair<long long,long long>,long long>>());
		for(j=0;j<N;j++)ed[j] = false;
		for(j=0;j<a[i%2].size();j++)if(dp[i][a[i%2][j].first.second] == a[i%2][j].second) {
			if(dp[i][a[i%2][j].first.second] >= s[i] && dp[i+1][a[i%2][j].first.second] < dp[i][a[i%2][j].first.second]) {
				dp[i+1][a[i%2][j].first.second] = dp[i][a[i%2][j].first.second];
				a[(i+1)%2].push_back(pair<pair<long long,long long>,long long>(pair<long long,long long>(h[2*N-1]-h[2*a[i%2][j].first.second]+dp[i+1][a[i%2][j].first.second],a[i%2][j].first.second),dp[i+1][a[i%2][j].first.second]));
			}
			f = true;
			for(k=a[i%2][j].first.second+1;k<=N && f;k++) {
				if(ed[k])f = false;
				else if(t[i] < v[k])f = false;
				else {
					if(dp[i][a[i%2][j].first.second]+h[max(2*a[i%2][j].first.second,2*k-1)]-h[2*a[i%2][j].first.second] >= s[i]) {
						if(dp[i+1][k] < dp[i][a[i%2][j].first.second]+h[max(2*a[i%2][j].first.second,2*k-1)]-h[2*a[i%2][j].first.second]) {
							dp[i+1][k] = dp[i][a[i%2][j].first.second]+h[max(2*a[i%2][j].first.second,2*k-1)]-h[2*a[i%2][j].first.second];
							a[(i+1)%2].push_back(pair<pair<long long,long long>,long long>(pair<long long,long long>(h[2*N-1]-h[2*k]+dp[i+1][k],k),dp[i+1][k]));
						}
					}
					ed[k] = true;
				}
			}
		}
	}
	long long ans = -1;
	for(i=0;i<=N;i++) {
		if(dp[M][i] != -1)ans = max(ans,t[M-1]-v[i]);
	}
	cout << ans << endl;
}
accuracy: 1
time_ms: 190
memory_kb: 26764
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
 
#define REP(i, n) for (ll i = 0; i < n; i++)
#define REPR(i, n) for (ll i = n; i >= 0; i--)
#define FOR(i, m, n) for (ll i = m; i < n; i++)
#define FORR(i, m, n) for (ll i = m; i >= n; i--)
#define REPO(i, n) for (ll i = 1; i <= n; i++)
#define ll long long
#define INF (ll)1 << 60
#define MINF (-1 * INF)
#define ALL(n) n.begin(), n.end()
#define MOD 1000000007
#define P pair<ll, ll>

ll n, m, v[5000], h[5000], t[5000], s[5000], str[3100];
int main() {
    cin >> n >> m;
    vector<vector<ll> > dp(3100, vector<ll>(3100, INF));
    dp[0][0] = 0;
    REPO(i, n) {
        cin >> v[i] >> h[i];
    }
    REPO(i, n) {
        v[i + 1] += v[i];
    }
    REPO(i, m) {
        cin >> t[i] >> s[i];
    }
    REPO(i, n) {//i個目まで買ったときの最大のstr
        str[i] += h[i];
        str[i + 1] += abs(h[i] - h[i + 1]) + str[i];
        //cout << i << "  ! " << str[i] << endl;
    }
    REP(i, m) {
        //if(dp[i][j])
        ll sonsitsu = dp[i][0];
        ll nowev = i + 1;
        REP(j, n + 1) {//jこ買った
            if(t[nowev] < v[j]) break;
            dp[nowev][j] = min(dp[nowev][j], sonsitsu);
            if(j > 0)sonsitsu = min(sonsitsu, dp[i][j] + abs(h[j] - h[j + 1]));

            dp[nowev][j] = min(dp[nowev][j], dp[i][j]);
            //powercheck
            ll okson = str[j] - s[nowev];
            if (okson < dp[nowev][j]) dp[nowev][j] = INF;
           // cout << i + 1 << " " << j << " " << dp[i + 1][j] << " " << okson << endl;
        }
    }
    ll mi = INF;
    REP(i, n + 1) {
        if (dp[m][i] < INF) mi = min(mi, i);
    }
    ll ans = t[m];
    if (mi == INF) {
        cout << -1 << endl;
        return 0;
    }
    ans -= v[mi];
    cout << ans << endl;
}
accuracy: 1
time_ms: 20
memory_kb: 78148
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
 
#define REP(i, n) for (ll i = 0; i < n; i++)
#define REPR(i, n) for (ll i = n; i >= 0; i--)
#define FOR(i, m, n) for (ll i = m; i < n; i++)
#define FORR(i, m, n) for (ll i = m; i >= n; i--)
#define REPO(i, n) for (ll i = 1; i <= n; i++)
#define ll long long
#define INF (ll)1 << 60
#define MINF (-1 * INF)
#define ALL(n) n.begin(), n.end()
#define MOD 1000000007
#define P pair<ll, ll>

ll n, m, v[5000], h[5000], t[5000], s[5000], str[2100];
int main() {
    cin >> n >> m;
    vector<vector<ll> > dp(3100, vector<ll>(3100, INF));
    dp[0][0] = 0;
    REPO(i, n) {
        cin >> v[i] >> h[i];
    }
    REPO(i, n) {
        v[i + 1] += v[i];
    }
    REPO(i, m) {
        cin >> t[i] >> s[i];
    }
    REPO(i, n) {//i個目まで買ったときの最大のstr
        str[i] += h[i];
        str[i + 1] += abs(h[i] - h[i + 1]) + str[i];
        //cout << i << "  ! " << str[i] << endl;
    }
    REP(i, m) {
        //if(dp[i][j])
        ll sonsitsu = dp[i][0];
        ll nowev = i + 1;
        REP(j, n + 1) {//jこ買った
            if(t[nowev] < v[j]) break;
            dp[nowev][j] = min(dp[nowev][j], sonsitsu);
            if(j > 0)sonsitsu = min(sonsitsu, dp[i][j] + abs(h[j] - h[j + 1]));

            dp[nowev][j] = min(dp[nowev][j], dp[i][j]);
            //powercheck
            ll okson = str[j] - s[nowev];
            if (okson < dp[nowev][j]) dp[nowev][j] = INF;
           // cout << i + 1 << " " << j << " " << dp[i + 1][j] << " " << okson << endl;
        }
    }
    ll mi = INF;
    REP(i, n + 1) {
        if (dp[m][i] < INF) mi = min(mi, i);
    }
    ll ans = t[m];
    if (mi == INF) {
        cout << -1 << endl;
        return 0;
    }
    ans -= v[mi];
    cout << ans << endl;
}
accuracy: 0.4666666666666667
time_ms: 10
memory_kb: 78144
final_rank: 20

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using u64 = unsigned long long;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

template <class T, class U>
vector<T> make_v(U size, const T& init){ return vector<T>(static_cast<size_t>(size), init); }

template<class... Ts, class U>
auto make_v(U size, Ts... rest) { return vector<decltype(make_v(rest...))>(static_cast<size_t>(size), make_v(rest...)); }

template<class T> void chmin(T &a, const T &b){ a = (a < b ? a : b); }
template<class T> void chmax(T &a, const T &b){ a = (a > b ? a : b); }

int main() {
    int n, m;
    cin >> n >> m;
    vector<int> vs(n), hs(n), ts(m), ss(m);
    vector<int> vsum(n+1);
    for (int i = 0; i < n; ++i) {
        cin >> vs[i] >> hs[i];
        vsum[i+1] = vsum[i]+vs[i];
    }
    for (int i = 0; i < m; ++i) cin >> ts[i] >> ss[i];
    auto dp = make_v(m+1, n+1, -INF<ll>);

    dp[0][0] = 0;
    for (int i = 1; i <= m; ++i) {
        ll val1 = -INF<ll>, val2 = dp[i-1][0];
        for (int j = 0; j <= n; ++j) {
            if(j){
                val1 += hs[j-1]; val2 += hs[j-1];
                if(j >= 2){
                    val1 += abs(hs[j-1]-hs[j-2]);
                }
            }
            val1 = max(val1, val2);
            val2 = dp[i-1][j];
            if(ts[i-1] >= vsum[j]) dp[i][j] = max(val1, val2);
            if(dp[i][j] < ss[i-1]) dp[i][j] = -INF<ll>;
        }
    }
    int ans = ts.back();
    for (int i = 0; i <= n; ++i) {
        if(dp.back()[i] >= 0){
            cout << ans << "\n";
            return 0;
        }
        if(i != n) ans -= vs[i];
    }
    cout << -1 << "\n";
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 26352
final_rank: 6