Problem:
エゴイ展 (EGOI Exhibition)
問題文
JOI 美術館には，
N
枚の絵が横一列に飾られている．美術館に展示されている絵には
M
個の種類があり，
1
から
M
までの番号が付けられている．左から
i
番目 (
1 ≦ i ≦ N
) の絵の種類は
A
i
であり，価値は
V
i
である．
ここで，
V
i
は負の数になることもある．
来月，JOI 美術館では「エゴイ展 2022」が開催予定であり，多くの来客が見込まれるため，見栄えを良くしたい．そこで館長の理恵さんは，隣り合う絵が同じ種類にならないように，いくつかの絵を撤去することにした．
一方で，評判を高めるため，残された絵の価値の合計をできるだけ大きくしたい．
絵の枚数，絵の種類数，
N
枚の絵の情報が与えられたとき，残された絵の価値の合計として考えられる最大値を求めるプログラムを作成せよ．
制約
1 ≦ N ≦ 150000
．
1 ≦ M ≦ N
．
1 ≦ A
i
≦ M
(
1 ≦ i ≦ N
)．
- 10000 ≦ V
i
≦ 10000
(
1 ≦ i ≦ N
)．
入力される値はすべて整数である．
入力
入力は以下の形式で標準入力から与えられる．
N
M
A
1
V
1
A
2
V
2
:
A
N
V
N
出力
標準出力に，残された絵の価値の合計として考えられる最大値を
1
行で出力せよ．
入出力例
入力例 1
3
1
1 107
1 123
1 100
出力例 1
123
左から
2
番目の絵のみを残した場合，価値の合計は
V
2
= 123
となる．
入力例 2
4
3
1 204
2 168
2 277
1 219
出力例 2
700
左から
1, 3, 4
番目の絵を残すのが最適である．
入力例 3
3
2
1 5
2 -1
1 5
出力例 3
9
すべての絵を残すのが最適である．
入力例 4
6
4
1 -123
2 -123
3 -123
4 -123
4 -123
3 -123
出力例 4
0
絵を
1
枚も残さないのが最適である．
入力例 5
30
4
2 -1358
4 -1405
4 2003
3 -1148
2 -1527
2 -2015
4 -2910
1 2133
2 2185
1 2249
3 1058
1 -1907
2 -3190
1 -2701
3 -2640
1 1685
3 1855
4 2398
3 -3158
2 1947
3 2947
2 -2197
4 1398
2 -3011
4 -1971
1 -2829
1 3094
2 2704
4 -2592
3 2910
出力例 5
30566
情報オリンピック日本委員会
作 『日本情報オリンピック第2回女性部門 本選 競技課題』

Submitted solutions:

code_snippet: #line 1 "/opt/library/template.hpp"
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using i64 = long long;
using u32 = unsigned int;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using f128 = __float128;

template <class T>
constexpr T infty = 0;
template <>
constexpr int infty<int> = 1'000'001'000;
template <>
constexpr ll infty<ll> = ll(infty<int>) * infty<int> * 2;
template <>
constexpr u32 infty<u32> = infty<int>;
template <>
constexpr u64 infty<u64> = infty<ll>;
template <>
constexpr i128 infty<i128> = i128(infty<ll>) * infty<ll>;
template <>
constexpr double infty<double> = infty<ll>;
template <>
constexpr long double infty<long double> = infty<ll>;
#define inf infty<ll>

using pi = pair<ll, ll>;
using vi = vector<ll>;
using vvi = vector<vector<ll>>;
template <class T>
using vc = vector<T>;
template <class T>
using vvc = vector<vc<T>>;
template <class T>
using vvvc = vector<vvc<T>>;
template <class T>
using vvvvc = vector<vvvc<T>>;
template <class T>
using vvvvvc = vector<vvvvc<T>>;
template <class T>
using pq = priority_queue<T>;
template <class T>
using pqg = priority_queue<T, vector<T>, greater<T>>;

#define vv(type, name, h, ...) \
  vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define vvv(type, name, h, w, ...)   \
  vector<vector<vector<type>>> name( \
      h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)       \
  vector<vector<vector<vector<type>>>> name( \
      a, vector<vector<vector<type>>>(       \
             b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))

#define rep1(a) for (ll _ = 0; _ < (ll)(a); ++_)
#define rep2(i, a) for (ll i = 0; i < (ll)(a); ++i)
#define rep3(i, a, b) for (ll i = a; i < (ll)(b); ++i)
#define rep4(i, a, b, c) for (ll i = a; i < (ll)(b); i += (c))
#define rrep1(a) for (ll i = (a)-1; i >= (ll)(0); --i)
#define rrep2(i, a) for (ll i = (a)-1; i >= (ll)(0); --i)
#define rrep3(i, a, b) for (ll i = (b)-1; i >= (ll)(a); --i)
#define rrep4(i, a, b, c) for (ll i = (b)-1; i >= (ll)(a); i -= (c))
#define overload4(a, b, c, d, e, ...) e
#define rep(...) overload4(__VA_ARGS__, rep4, rep3, rep2, rep1)(__VA_ARGS__)
#define rrep(...) overload4(__VA_ARGS__, rrep4, rrep3, rrep2, rrep1)(__VA_ARGS__)

#define all(x) (x).begin(),(x).end()
#define len(x) (ll)(x.size())
#define elif else if
#define bit(x, i) (((x)>>(i))&1)

#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second

#define stoi stoll
#define abs llabs

#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define LB(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define UB(c, x) distance((c).begin(), upper_bound(all(c), (x)))
#define UNIQUE(x) \
  sort(all(x)), x.erase(unique(all(x)), x.end()), x.shrink_to_fit()

ll popcnt(ll x) { return __builtin_popcountll(x); }
ll popcnt(u64 x) { return __builtin_popcountll(x); }
ll popcnt_mod_2(ll x) { return __builtin_parityll(x); }
ll popcnt_mod_2(u64 x) { return __builtin_parityll(x); }
ll topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
ll topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
ll lowbit(ll x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
ll lowbit(u64 x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }

template <typename T>
T floor(T a, T b) {
  return a / b - (a % b && (a ^ b) < 0);
}
template <typename T>
T ceil(T x, T y) {
  return floor(x + y - 1, y);
}
template <typename T>
T bmod(T x, T y) {
  return x - y * floor(x, y);
}
template <typename T>
pair<T, T> divmod(T x, T y) {
  T q = floor(x, y);
  return {q, x - q * y};
}

template<typename T> T SUM(const vector<T> &A) {
  T s = 0; for (auto &&a: A) s += a;
  return s;
}

template <typename T>
T POP(queue<T> &que) {
  T a = que.front();
  que.pop();
  return a;
}
template <typename T>
T POP(deque<T> &que) {
  T a = que.front();
  que.pop_front();
  return a;
}
template <typename T>
T POP(pq<T> &que) {
  T a = que.top();
  que.pop();
  return a;
}
template <typename T>
T POP(pqg<T> &que) {
  T a = que.top();
  que.pop();
  return a;
}
template <typename T>
T POP(vc<T> &que) {
  T a = que.back();
  que.pop_back();
  return a;
}

template <typename F>
ll binary_search(F check, ll ok, ll ng, bool check_ok = true) {
  if (check_ok) assert(check(ok));
  while (abs(ok - ng) > 1) {
    auto x = (ng + ok) / 2;
    (check(x) ? ok : ng) = x;
  }
  return ok;
}
template <typename F>
f128 binary_search_real(F check, f128 ok, f128 ng, ll iter = 100) {
  rep(iter) {
    f128 x = (ok + ng) / 2;
    (check(x) ? ok : ng) = x;
  }
  return (ok + ng) / 2;
}

// ? は -1
vc<int> s_to_vi(const string &S, char first_char) {
  vc<int> A(S.size());
  rep(i, S.size()) { A[i] = (S[i] != '?' ? S[i] - first_char : -1); }
  return A;
}

template <typename T, typename U>
vc<T> cumsum(vc<U> &A, ll off = 1) {
  ll N = A.size();
  vc<T> B(N + 1);
  rep(i, N) { B[i + 1] = B[i] + A[i]; }
  if (off == 0) B.erase(B.begin());
  return B;
}

// stable sort
template <typename T>
vi argsort(const vector<T> &A) {
  vi ids(len(A));
  iota(all(ids), 0);
  sort(all(ids),
       [&](ll i, ll j) { return (A[i] == A[j] ? i < j : A[i] < A[j]); });
  return ids;
}

// A[I[0]], A[I[1]], ...
template <typename T>
vc<T> rearrange(const vc<T> &A, const vi &I) {
  vc<T> B(len(I));
  rep(i, len(I)) B[i] = A[I[i]];
  return B;
}

template<typename T> inline bool chmax(T &a, T b) {return ((a<b)?(a=b,true):(false));}
template<typename T> inline bool chmin(T &a, T b) {return ((a>b)?(a=b,true):(false));}

inline void wt(const char c) { cout << c; }
inline void wt(const string s) { cout << s; }
inline void wt(const char *s) { cout << s; }

template <typename T>
void wt_integer(T x) {
  if (x < 0) { cout << (i64)(x); }
  else { cout << (u64)(x); }
}
template <typename T>
void wt_real(T x) {
  cout << fixed << setprecision(15) << (long double)(x);
}

inline void wt(int x) { wt_integer(x); }
inline void wt(ll x) { wt_integer(x); }
inline void wt(i128 x) { wt_integer(x); }
inline void wt(u32 x) { wt_integer(x); }
inline void wt(u64 x) { wt_integer(x); }
inline void wt(u128 x) { wt_integer(x); }
inline void wt(double x) { wt_real(x); }
inline void wt(long double x) { wt_real(x); }
inline void wt(f128 x) { wt_real(x); }

template <class T, class U>
void wt(const pair<T, U> val) {
  wt(val.first); wt(' '); wt(val.second);
}
template <size_t N = 0, typename T>
void wt_tuple(const T t) {
  if constexpr (N < std::tuple_size<T>::value) {
    if constexpr (N > 0) { wt(' '); }
    const auto x = std::get<N>(t);
    wt(x);
    wt_tuple<N + 1>(t);
  }
}
template <class... T>
void wt(tuple<T...> tpl) {
  wt_tuple(tpl);
}
template <class T, size_t S>
void wt(const array<T, S> val) {
  auto n = val.size();
  for (size_t i = 0; i < n; i++) {
    if (i) wt(' ');
    wt(val[i]);
  }
}
template <class T>
void wt(const vector<T> val) {
  auto n = val.size();
  for (size_t i = 0; i < n; i++) {
    if (i) wt(' ');
    wt(val[i]);
  }
}

void print() { wt('\n'); }
template <class Head, class... Tail>
void print(Head &&head, Tail &&... tail) {
  wt(head);
  if (sizeof...(Tail)) wt(' ');
  print(forward<Tail>(tail)...);
}

void YES(bool t = 1) { print(t ? "YES" : "NO"); }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { print(t ? "Yes" : "No"); }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { print(t ? "yes" : "no"); }
void no(bool t = 1) { yes(!t); }
void onez(bool t = 1) { print(t ? 1 : 0); }
#define endl '\n'
#define dump(x) {cerr << #x " = " << x << '\n';}
#line 2 "main.cpp"

int solve();
int main() {
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  while (!solve()) {break;}
  return 0;
}

int solve() {
  ll N, M;
  cin >> N >> M;
  vi A(N), V(N);
  rep(i, N) cin >> A[i] >> V[i];
  vc<pi> dp1(N, mp(-inf, -1)), dp2(N, mp(-inf, -1));
  dp1[0] = mp(V[0], A[0]);
  dp2[0] = mp(0, -1);
  rep(i, 1, N) {
    vc<pi> v;
    if (dp1[i-1].se != A[i]) v.eb(mp(dp1[i-1].fi + V[i], A[i]));
    if (dp2[i-1].se != A[i]) v.eb(mp(dp2[i-1].fi + V[i], A[i]));
    v.eb(mp(dp1[i-1].fi, dp1[i-1].se));
    v.eb(mp(dp2[i-1].fi, dp2[i-1].se));
    sort(all(v), greater<pi>());
    dp1[i] = v[0];
    rep(j, 1, len(v)) {
      if (v[j].se == v[0].se) continue;
      dp2[i] = v[j];
      break;
    }
  }
  print(dp1[N-1].fi);
  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 10216
final_rank: 6

code_snippet: #include "bits/stdc++.h"

#define REP(i,num) for(ll i=0;i<(num);++i)
#define FOR(i,c,num) for(ll (i)=(c);(i)<(num);++(i))
#define LOOP(i) while(i--)
#define ALL(c) c.begin(),c.end()
#define PRINTALL(c) for(auto pitr=c.begin();pitr!=c.end();++pitr){cout<<*pitr;if(next(pitr,1)!=c.end())cout<<' ';}cout<<endl;
#define PAIRCOMP(c,comp) [](const pair<ll,ll>& lhs,const pair<ll,ll>& rhs){return lhs.c comp rhs.c;}

using namespace std;
using ll = long long;
using ull = unsigned long long;
using vll = vector<ll>;
using vvll = vector<vector<ll>>;

constexpr ll atcoder_mod = 1e9+7;

template<typename T=ll>
T in(){ T x; cin >> x; return (x); }
template<typename T=ll,typename C=vector<T>>
C vecin(int N){ C x(N);REP(i,N){ x[i]=in<T>(); }return x; }
template<typename T=ll,size_t N>
array<T,N> arrin(){array<T,N> x;REP(i,N){ x[i]=in<T>(); }return x;}

void vout(){ cout << endl; }
template<typename Head,typename... Tail>
void vout(Head&& h,Tail&&... t){ cout << ' ' << h;vout(forward<Tail>(t)...); }
void out(){ cout << endl; }
template<typename Head,typename... Tail>
void out(Head&& h,Tail&&... t){ cout << h;vout(forward<Tail>(t)...); }

template<typename T>
bool chmax(T& a,T b){ if(a<b){ a=b;return true; }return false; }
template<typename T>
bool chmin(T& a,T b){ if(a>b){ a=b;return true; }return false; }

class RangeUpdate{
public:
	virtual ll fa(ll x,ll m)=0;
	virtual ll fm(ll m1,ll m2)=0;
	ll em;
};

class RangeUpdateChange:public RangeUpdate{
public:
	RangeUpdateChange(){ em = numeric_limits<ll>::max(); }
	ll fa(ll x,ll m){ return m; }
	ll fm(ll m1,ll m2){ return m2; }
};

class RangeQuery{
public:
	virtual ll fx(ll x1,ll x2)=0;
	virtual ll fp(ll m,ll n)=0;
	ll ex;
};

class RangeQueryMax:public RangeQuery{
public:
	RangeQueryMax(){ ex = numeric_limits<ll>::lowest(); }
	ll fx(ll x1,ll x2){ return max(x1,x2); }
	ll fp(ll m,ll n){ return m; }
};

class SegmentTree{
	unique_ptr<RangeUpdate> range_update;
	unique_ptr<RangeQuery> range_query;

	/* lazy eval */
	void Eval(int k,int len){
		if(lazy[k]==range_update->em) return;  // 更新するものが無ければ終了
		if(k<size-1){            // 葉でなければ子に伝搬
			lazy[k*2+1] = range_update->fm(lazy[k*2+1],lazy[k]);
			lazy[k*2+2] = range_update->fm(lazy[k*2+2],lazy[k]);
		}
		// 自身を更新
		dat[k] = range_update->fa(dat[k],range_query->fp(lazy[k],len));
		lazy[k] = range_update->em;
	}

	ll Query(ll a,ll b,ll k,ll l,ll r){
		Eval(k,r-l);
		if(r<=a || b<=l){  // 完全に外側の時
			return range_query->ex;
		}
		else if(a <= l && r <= b){  // 完全に内側の時
			return dat[k];
		}
		else{  // 一部区間が被る時
			ll vl = Query(a,b,k*2+1,l,(l+r)/2);
			ll vr = Query(a,b,k*2+2,(l+r)/2,r);
			return range_query->fx(vl,vr);
		}
	}

	void Update(ll a,ll b,ll x,ll k,ll l,ll r) {
		Eval(k,r-l);
		if(a<=l && r<=b){  // 完全に内側の時
			lazy[k] = range_update->fm(lazy[k],x);
			Eval(k,r-l);
		}
		else if(a<r && l<b){                     // 一部区間が被る時
			Update(a,b,x,k*2+1,l,(l+r)/2);  // 左の子
			Update(a,b,x,k*2+2,(l+r)/2,r);  // 右の子
			dat[k] = range_query->fx(dat[k*2+1],dat[k*2+2]);
		}
	}
public:
	ll size;
	vector<ll> dat;
	vector<ll> lazy;
	SegmentTree(ll N,unique_ptr<RangeUpdate> rup,unique_ptr<RangeQuery> rqp)
		: range_update(std::move(rup)),range_query(std::move(rqp)){
		dat.resize(max(4*N,4ll),range_query->ex);
		lazy.resize(max(4*N,4ll),range_update->em);
		ll x = 1;
		while(N>x) x *= 2;
		size = x;
	}
	void Set(int i,ll x){ dat[i+size-1]=x; }
	void Build(){
		for(ll k=size-2ll;k>=0;k--) dat[k] = range_query->fx(dat[2*k+1],dat[2*k+2]);
	}

	void Update(ll a,ll b,ll x){ Update(a,b,x,0,0,size); }
	ll Query(int a,int b){ return Query(a,b,0,0,size); }
};

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	cout<<fixed<<setprecision(10);
	
	auto N=in(),M=in();

	ll len = M+2ll;
	SegmentTree seg_tree(len,make_unique<RangeUpdateChange>(),make_unique<RangeQueryMax>());
	REP(i,len){
		seg_tree.Set(i,0);
	}
	seg_tree.Build();

	LOOP(N){
		ll t=in(),v=in();
		auto L=seg_tree.Query(0,t);
		auto M=seg_tree.Query(t,t+1);
		auto R=seg_tree.Query(t+1,len);
		seg_tree.Update(t,t+1,max(M,max(L,R)+v));
	}
	out(seg_tree.Query(0,len));
	return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 12472
final_rank: 9

code_snippet: /* -*- coding: utf-8 -*-
 *
 * 0733.cc: エゴイ展 (EGOI Exhibition)
 */

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

/* constant */

const int MAX_N = 150000;
const int MAX_M = 150000;

/* typedef */

template <typename T>
struct SegTreeMax {
  int e2;
  vector<T> nodes;
  T defv;
  SegTreeMax() {}

  void init(int n, T _defv) {
    defv = _defv;
    for (e2 = 1; e2 < n; e2 <<= 1);
    nodes.assign(e2 * 2, defv);
  }

  T &geti(int i) { return nodes[e2 - 1 + i]; }
  void seti(int i, T v) { geti(i) = v; }

  void setall() {
    for (int j = e2 - 2; j >= 0; j--)
      nodes[j] = max(nodes[j * 2 + 1], nodes[j * 2 + 2]);
  }

  void set(int i, T v) {
    int j = e2 - 1 + i;
    nodes[j] = v;
    while (j > 0) {
      j = (j - 1) / 2;
      nodes[j] = max(nodes[j * 2 + 1], nodes[j * 2 + 2]);
    }
  }

  T max_range(int r0, int r1, int k, int i0, int i1) {
    if (r1 <= i0 || i1 <= r0) return defv;
    if (r0 <= i0 && i1 <= r1) return nodes[k];

    int im = (i0 + i1) / 2;
    T v0 = max_range(r0, r1, k * 2 + 1, i0, im);
    T v1 = max_range(r0, r1, k * 2 + 2, im, i1);
    return max(v0, v1);
  }
  T max_range(int r0, int r1) { return max_range(r0, r1, 0, 0, e2); }
};

/* global variables */

int as[MAX_N], vs[MAX_N];
SegTreeMax<int> st;

/* subroutines */

/* main */

int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  for (int i = 0; i < n; i++) scanf("%d%d", as + i, vs + i), as[i]--;

  st.init(m, 0);
  for (int i = 0; i < n; i++) {
    int di =
      max(st.max_range(0, as[i]), st.max_range(as[i] + 1, m)) + vs[i];
    if (st.geti(as[i]) < di) st.set(as[i], di);
  }

  int maxd = 0;
  for (int i = 0; i < m; i++) maxd = max(maxd, st.geti(i));

  printf("%d\n", maxd);
  
  return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 5760
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define all(A) A.begin(),A.end()
using vll = vector<ll>;
#define rep(i, n) for (long long i = 0; i < (long long)(n); i++)

template<class T>
struct segtree {//0index
    int n;
    vector<T> V;
    segtree(int siz) :n(), V(siz * 4, e()) {
        int x = 1;
        while (siz > x) {
            x *= 2;
        }
        n = x;
    }

    void update(int id, T x) {
        id += n;
        V[id] = x;
        while (id > 1) {
            id = id / 2;
            V[id] = op(V[id * 2], V[id * 2+1]);
        }
    }

    T prod(int a, int b) {//op[a,b)
        return quer(a, b, 1, 0, n);
    };
    T quer(int a, int b, int k, int l, int r) {
        if (r <= a || b <= l)return e();
        else if (a <= l && r <= b)return V[k];
        else {
            return op(quer(a, b, k * 2, l, (l + r) / 2), quer(a, b, k * 2 + 1, (l + r) / 2, r));
        }
    };


    T op(T a, T b) {
        return max(a,b);
    };
    T e() {
        return 0;
    };
};


ll gcd(ll(a), ll(b)) {
    ll c = a;
    while (a % b != 0) {
        c = a % b;
        a = b;
        b = c;
    }
    return b;
}


int main() {
    ll N, M;
    cin >> N >> M;
    segtree<ll> seg(N + 1);
    rep(i, N + 1)seg.update(i,0);
    rep(i, N) {
        ll A, V;
        cin >> A >> V;
        ll M = seg.prod(A,A+1);
        seg.update(A, -1);
        ll P=seg.prod(0,N+1);
        M = max(M, P + V);
        seg.update(A, M);
    }
    cout << seg.prod(0,N+1) << endl;

}
accuracy: 1
time_ms: 80
memory_kb: 7800
final_rank: 7

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001



#define SIZE 150005

int N;
ll table[6*SIZE];
ll A[SIZE],V[SIZE];

void init(int first_N){
	N = 1;
	while(N < first_N)N *= 2;
}

void update(int loc,ll value){
	loc += N-1;

	table[loc] = value;

	if(N == 1)return;

	int parent = (loc-1)/2;

	while(true){
		table[parent] = max(table[2*parent+1],table[2*parent+2]);

		if(parent == 0)break;
		else{
			parent = (parent-1)/2;
		}
	}
}


ll query(int search_left,int search_right,int node_id,int node_left,int node_right){

	//今回のノードが検索区間をカバーしていなければ、結果に関係ない値を返す
	if(search_right < node_left || search_left > node_right){

		return -HUGE_NUM;
	}

	//今回のノードの区間が、検索区間の部分区間である場合、今回のノードの値を返す
	if(search_left <= node_left && search_right >= node_right){
		return table[node_id];
	}

	//今回のノードの区間に、一部検索区間と重なっている区間がある場合→再帰的に子どもに尋ねる
	ll left_max = query(search_left,search_right,2*node_id+1,node_left,(node_left+node_right)/2);
	ll right_max = query(search_left,search_right,2*node_id+2,(node_left+node_right)/2+1,node_right);

	return max(left_max,right_max);
}


int main(){

	int first_N,M;
	scanf("%d %d",&first_N,&M);

	init(M+1); //■0を含めるため、M+1種類

	//0～N-2が上位構造のアドレス、N-1～2*N-2が最小要素のアドレス
	for(int i = 0; i <= 2*N-2; i++)table[i] = -HUGE_NUM;

	update(0,0); //ダミー

	ll ans = 0;

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

		scanf("%lld %lld",&A[i],&V[i]);

		//自分以外の種類の最大値
		ll tmp = query(0,A[i]-1,0,0,N-1);
		if(A[i] != M){

			chmax(tmp,query(A[i]+1,M,0,0,N-1));
		}

		ll pre = query(A[i],A[i],0,0,N-1); //同種の過去最大値

		if(pre >= tmp+V[i]){
			continue;
		}

		update(A[i],tmp+V[i]);
		chmax(ans,tmp+V[i]);
	}

	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 9664
final_rank: 8

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
#include <bitset>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

template <class S, S (*op)(S, S), S (*e)()>
struct segtree {
    int n;
    vector<S> tree;
    segtree() : segtree(0) {}
    segtree(int n) : n(n), tree(vector<S>(n<<1, e())) {}
    void update(int k) { tree[k] = op(tree[k<<1|0], tree[k<<1|1]); }
    S operator[](int i) {return tree[i+n]; }
    void set(int i, S x) {
        i += n;
        tree[i] = x;
        while(i >>= 1) {
            update(i);
        }
    }
    // [l,r)
    S query(int l, int r) {
        S res = e();
        for(l += n, r += n; l < r; l >>= 1, r >>= 1){
            if(l & 1) res = op(res, tree[l++]);
            if(r & 1) res = op(res, tree[--r]);
        }
        return res;
    }
};

ll op(ll a,ll b){return max(a,b);}
ll e() {return -1e18;}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n,m; cin >> n >> m;
    vector<int> a(n),v(n);
    for(int i=0;i<n;i++){
        cin >> a[i] >> v[i];
    }
    segtree<ll, op, e> seg(m+1);
    seg.set(0,0);
    for(int i=0;i<n;i++){
        ll u = max(seg.query(0, a[i]), seg.query(a[i]+1, m+1));
        if(seg[a[i]] < u+v[i]){
            seg.set(a[i],u+v[i]);
        }
    }
    cout << seg.query(0, m+1) << endl;
}
accuracy: 1
time_ms: 30
memory_kb: 6708
final_rank: 2

code_snippet: #line 1 "a.cpp"
#define PROBLEM ""
#line 2 "/home/kuhaku/home/github/algo/lib/template/template.hpp"
#pragma GCC target("sse4.2,avx2,bmi2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
template <class T, class U>
bool chmax(T &a, const U &b) {
    return a < (T)b ? a = (T)b, true : false;
}
template <class T, class U>
bool chmin(T &a, const U &b) {
    return (T)b < a ? a = (T)b, true : false;
}
constexpr std::int64_t INF = 1000000000000000003;
constexpr int Inf = 1000000003;
constexpr int MOD = 1000000007;
constexpr int MOD_N = 998244353;
constexpr double EPS = 1e-7;
constexpr double PI = M_PI;
#line 3 "/home/kuhaku/home/github/algo/lib/math/pow.hpp"

std::int64_t safe_mod(std::int64_t a, std::int64_t mod) {
    a %= mod;
    return a >= 0 ? a : a + mod;
}

std::int64_t pow_int(std::int64_t a, std::int64_t n) {
    assert(n >= 0);
    std::int64_t res = 1, mul = a;
    for (; n > 0; n >>= 1) {
        if (n & 1) res *= mul;
        mul *= mul;
    }
    return res;
}

std::int64_t inv_mod(std::int64_t a, std::int64_t mod) {
    std::int64_t b = mod, u = 1, v = 0, t;
    while (b > 0) {
        t = a / b;
        std::swap(a -= t * b, b);
        std::swap(u -= t * v, v);
    }
    return u >= 0 ? u % mod : (mod - (-u) % mod) % mod;
}

std::int64_t pow_mod(std::int64_t a, std::int64_t n, std::int64_t mod) {
    if (n < 0) return inv_mod(pow_mod(a, -n, mod), mod);
    std::int64_t res = 1, mul = safe_mod(a, mod);
    for (; n > 0; n >>= 1) {
        if (n & 1) (res *= mul) %= mod;
        (mul *= mul) %= mod;
    }
    return res;
}

int ceil_pow2(std::int64_t n) {
    int x = 0;
    while ((std::uint64_t(1) << x) < (std::uint64_t)(n)) ++x;
    return x;
}

int floor_pow2(std::int64_t n) {
    int x = 0;
    while ((std::uint64_t(1) << (x + 1)) <= (std::uint64_t)(n)) ++x;
    return x;
}
#line 3 "/home/kuhaku/home/github/algo/lib/segment_tree/monoid.hpp"

template <class T>
struct Add {
    using value_type = T;
    static constexpr T id = T(0);
    static constexpr T op(const T &lhs, const T &rhs) { return lhs + rhs; }

    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs + rhs;
    }
};

template <class T>
struct And {
    using value_type = T;
    static constexpr T id = std::numeric_limits<T>::max();
    static constexpr T op(const T &lhs, const T &rhs) { return lhs & rhs; }

    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs & rhs;
    }
};

template <class T>
struct Or {
    using value_type = T;
    static constexpr T id = T(0);
    static constexpr T op(const T &lhs, const T &rhs) { return lhs | rhs; }

    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs | rhs;
    }
};

template <class T>
struct Xor {
    using value_type = T;
    static constexpr T id = T(0);
    static constexpr T op(const T &lhs, const T &rhs) { return lhs ^ rhs; }

    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs ^ rhs;
    }
};

template <class T>
struct Min {
    using value_type = T;
    static constexpr T id = std::numeric_limits<T>::max();
    static constexpr T op(const T &lhs, const T &rhs) { return std::min(lhs, rhs); }

    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return std::min((U)lhs, rhs);
    }
};

template <class T>
struct Max {
    using value_type = T;
    static constexpr T id = std::numeric_limits<T>::min();
    static constexpr T op(const T &lhs, const T &rhs) { return std::max(lhs, rhs); }

    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return std::max((U)lhs, rhs);
    }
};

template <class T>
struct Update {
    using value_type = T;
    static constexpr T id = std::numeric_limits<T>::max();
    static constexpr T op(const T &lhs, const T &rhs) { return lhs == Update::id ? rhs : lhs; }

    template <class U>
    static constexpr U f(T lhs, U rhs) {
        return lhs == Update::id ? rhs : lhs;
    }
};

template <class T>
struct Affine {
    using value_type = std::pair<T, T>;
    static constexpr std::pair<T, T> id = std::pair<T, T>(1, 0);
    static constexpr std::pair<T, T> op(std::pair<T, T> lhs, std::pair<T, T> rhs) {
        return {lhs.first * rhs.first, lhs.first * rhs.second + lhs.second};
    }
};

template <class M>
struct Rev {
    using T = typename M::value_type;
    using value_type = T;
    static constexpr T id = M::id;
    static constexpr T op(T lhs, T rhs) { return M::op(rhs, lhs); }
};
#line 5 "/home/kuhaku/home/github/algo/lib/segment_tree/segment_tree.hpp"

/**
 * @brief セグメント木
 * @see https://noshi91.hatenablog.com/entry/2020/04/22/212649
 *
 * @tparam M モノイド
 */
template <class M>
struct segment_tree {
  private:
    using T = typename M::value_type;

  public:
    segment_tree() : segment_tree(0) {}
    explicit segment_tree(int n, T e = M::id) : segment_tree(std::vector<T>(n, e)) {}
    template <class U>
    explicit segment_tree(const std::vector<U> &v) : _n(v.size()) {
        this->_log = ceil_pow2(this->_n);
        this->_size = 1 << this->_log;
        this->data = std::vector<T>(this->_size << 1, M::id);
        for (int i = 0; i < this->_n; ++i) this->data[this->_size + i] = T(v[i]);
        for (int i = this->_size - 1; i >= 1; --i) this->update(i);
    }

    const T &operator[](int k) const { return this->data[k + this->_size]; }
    T at(int k) const { return this->operator[](k); }
    T get(int k) const { return this->operator[](k); }

    void set(int k, T val) {
        assert(0 <= k && k < this->_n);
        k += this->_size;
        this->data[k] = val;
        for (int i = 1; i <= this->_log; ++i) this->update(k >> i);
    }
    void reset(int k) { this->set(k, M::id); }

    T all_prod() const { return this->data[1]; }
    T prod(int a, int b) const {
        assert(0 <= a && b <= this->_n);
        T l = M::id, r = M::id;
        for (a += this->_size, b += this->_size; a < b; a >>= 1, b >>= 1) {
            if (a & 1) l = M::op(l, this->data[a++]);
            if (b & 1) r = M::op(this->data[--b], r);
        }
        return M::op(l, r);
    }

    template <class F>
    int max_right(F f) const {
        return this->max_right(0, f);
    }

    template <class F>
    int max_right(int l, F f) const {
        assert(0 <= l && l <= this->_n);
        assert(f(M::id));
        if (l == this->_n) return this->_n;
        l += this->_size;
        T sm = M::id;
        do {
            while (l % 2 == 0) l >>= 1;
            if (!f(M::op(sm, this->data[l]))) {
                while (l < this->_size) {
                    l = (2 * l);
                    if (f(M::op(sm, this->data[l]))) {
                        sm = M::op(sm, this->data[l]);
                        l++;
                    }
                }
                return l - this->_size;
            }
            sm = M::op(sm, this->data[l]);
            l++;
        } while ((l & -l) != l);
        return this->_n;
    }

    int max_right(T x) const { return this->max_right(0, x); }

    int max_right(int l, T x) const {
        return this->max_right(l, [&x](auto y) {
            return !(y < x);
        });
    }

    template <class F>
    int min_left(F f) const {
        return this->min_left(this->_n, f);
    }

    template <class F>
    int min_left(int r, F f) const {
        assert(0 <= r && r <= this->_n);
        assert(f(M::id));
        if (r == 0) return 0;
        r += this->_size;
        T sm = M::id;
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!f(M::op(this->data[r], sm))) {
                while (r < this->_size) {
                    r = (2 * r + 1);
                    if (f(M::op(this->data[r], sm))) {
                        sm = M::op(this->data[r], sm);
                        r--;
                    }
                }
                return r + 1 - this->_size;
            }
            sm = M::op(this->data[r], sm);
        } while ((r & -r) != r);
        return 0;
    }

    int min_left(T x) const { return this->min_left(this->_n, x); }

    int min_left(int r, T x) const {
        return this->min_left(r, [&x](auto y) {
            return !(y < x);
        });
    }

  private:
    int _n, _size, _log;
    std::vector<T> data;

    void update(int k) { this->data[k] = M::op(this->data[2 * k], this->data[2 * k + 1]); }
};
#line 3 "/home/kuhaku/home/github/algo/lib/template/macro.hpp"
#define FOR(i, m, n) for (int i = (m); i < int(n); ++i)
#define FORR(i, m, n) for (int i = (m)-1; i >= int(n); --i)
#define FORL(i, m, n) for (int64_t i = (m); i < int64_t(n); ++i)
#define rep(i, n) FOR (i, 0, n)
#define repn(i, n) FOR (i, 1, n + 1)
#define repr(i, n) FORR (i, n, 0)
#define repnr(i, n) FORR (i, n + 1, 1)
#define all(s) (s).begin(), (s).end()
#line 3 "/home/kuhaku/home/github/algo/lib/template/sonic.hpp"
struct Sonic {
    Sonic() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
    }

    constexpr void operator()() const {}
} sonic;
#line 5 "/home/kuhaku/home/github/algo/lib/template/atcoder.hpp"
using namespace std;
using ll = std::int64_t;
using ld = long double;
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
    return is >> p.first >> p.second;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
    for (T &i : v) is >> i;
    return is;
}
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
    return os << '(' << p.first << ',' << p.second << ')';
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
    for (auto it = v.begin(); it != v.end(); ++it) {
        os << (it == v.begin() ? "" : " ") << *it;
    }
    return os;
}
template <class Head, class... Tail>
void co(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cout << head << '\n';
    else std::cout << head << ' ', co(std::forward<Tail>(tail)...);
}
template <class Head, class... Tail>
void ce(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cerr << head << '\n';
    else std::cerr << head << ' ', ce(std::forward<Tail>(tail)...);
}
template <typename T, typename... Args>
auto make_vector(T x, int arg, Args... args) {
    if constexpr (sizeof...(args) == 0) return std::vector<T>(arg, x);
    else return std::vector(arg, make_vector<T>(x, args...));
}
void setp(int n) {
    std::cout << std::fixed << std::setprecision(n);
}
void Yes(bool is_correct = true) {
    std::cout << (is_correct ? "Yes" : "No") << '\n';
}
void No(bool is_not_correct = true) {
    Yes(!is_not_correct);
}
void YES(bool is_correct = true) {
    std::cout << (is_correct ? "YES" : "NO") << '\n';
}
void NO(bool is_not_correct = true) {
    YES(!is_not_correct);
}
void Takahashi(bool is_correct = true) {
    std::cout << (is_correct ? "Takahashi" : "Aoki") << '\n';
}
void Aoki(bool is_not_correct = true) {
    Takahashi(!is_not_correct);
}
#line 4 "a.cpp"

int main(void) {
    int n, m;
    cin >> n >> m;
    segment_tree<Max<ll>> st(m);
    rep (i, m) st.set(i, 0);
    while (n--) {
        ll x, y;
        cin >> x >> y;
        --x;
        ll ans = 0;
        chmax(ans, st.prod(0, x));
        chmax(ans, st.prod(x + 1, m));
        ans += y;
        if (st.get(x) < ans)
            st.set(x, ans);
    }
    cout << st.all_prod() << endl;

    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 8300
final_rank: 5

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

using namespace std;

#define rep(i,n) for(int i=0;i<(n);++i)
#define reps(i,n) for(int i=1;i<=(n);++i)
#define all(x) begin(x),end(x)
#define Fixed fixed << setprecision(12)
#define updiv(a, b) (((a) + (b) - 1) / (b))
using pii = pair<int,int>;
constexpr int32_t INF  = 0x3f3f3f3f;
constexpr int_fast64_t LINF = 0x3f3f3f3f3f3f3f3fLL;
constexpr int mod1 = 1e9+7;
constexpr int mod2 = 998244353;

template <class Func>
class FixPoint : Func {
public:
    explicit constexpr FixPoint(Func&& f) noexcept : Func(forward<Func>(f)) {}

    template <class... Args>
    constexpr decltype(auto) operator()(Args&&... args) const {
        return Func::operator()(*this, std::forward<Args>(args)...);
    }
};

template <class Func>
static inline constexpr decltype(auto) makeFixPoint(Func&& f) noexcept {
    return FixPoint<Func>{forward<Func>(f)};
}

template<class T, class U> istream& operator>>(istream& is, pair<T, U>& p){ is >> p.first >> p.second; return (is); }
template<class T, class U> ostream& operator<<(ostream& os, pair<T, U>& p){ os << p.first << ' ' << p.second; return (os); }
template<class T> istream& operator>>(istream& is, vector<T>& v){ for (auto &&e : v) is >> e; return (is); }
template<class T> ostream& operator<<(ostream& os, vector<T>& v){ for (auto &&e : v) os << e << ' '; return (os); }

template <class A, class B> inline bool chmax(A &a, const B &b) { return b > a && (a = b, true); }
template <class A, class B> inline bool chmin(A &a, const B &b) { return b < a && (a = b, true); }

template <class T> using max_heap = priority_queue<T>;
template <class T> using min_heap = priority_queue<T, vector<T>, greater<T> >;
template <class A, class B> using umap = unordered_map<A, B>;
template <class T> using uset = unordered_set<T>;

template <class T> using Max_Heap = __gnu_pbds::priority_queue<T, less<T>, __gnu_pbds::rc_binomial_heap_tag>;
template <class T> using Min_Heap = __gnu_pbds::priority_queue<T, greater<T>, __gnu_pbds::rc_binomial_heap_tag>;
template <class T> using Set = __gnu_pbds::tree<T, __gnu_pbds::null_type, less<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
template <class K, class V> using Umap = __gnu_pbds::gp_hash_table<K, V>;
template <class T> using Rope = __gnu_cxx::rope<T>;
using Trie = __gnu_pbds::trie<string, __gnu_pbds::null_type, __gnu_pbds::trie_string_access_traits<>, __gnu_pbds::pat_trie_tag, __gnu_pbds::trie_prefix_search_node_update>;

template <class T> void bye(T x){ cout << x << '\n'; exit(0); }
inline int square(int a){ return (a * a); }

constexpr int dx[] = {1,0,-1,0,1,1,-1,-1};
constexpr int dy[] = {0,-1,0,1,1,-1,-1,1};

template< typename Monoid, typename F >
struct SegmentTree {
    int sz;
    vector< Monoid > seg;

    const F f;
    const Monoid M1;
    
    SegmentTree(int n, const F f, const Monoid &M1) : f(f), M1(M1) {
        sz = 1;
        while(sz < n) sz <<= 1;
        seg.assign(2 * sz, M1);
    }

    void set(int k, const Monoid &x) {
        seg[k + sz] = x;
    }

    void build() {
        for(int k = sz - 1; k > 0; k--) {
            seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
        }
    }

    void update(int k, const Monoid &x) {
        k += sz;
        seg[k] = x;
        while(k >>= 1) {
            seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
        }
    }

    Monoid query(int a, int b) {
        Monoid L = M1, R = M1;
        for(a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
            if(a & 1) L = f(L, seg[a++]);
            if(b & 1) R = f(seg[--b], R);
        }
        return f(L, R);
    }

    Monoid operator[](const int &k) const {
        return seg[k + sz];
    }

    template< typename C >
    int find_subtree(int a, const C &check, Monoid &M, bool type) {
        while(a < sz) {
            Monoid nxt = type ? f(seg[2 * a + type], M) : f(M, seg[2 * a + type]);
            if(check(nxt)) a = 2 * a + type;
            else M = nxt, a = 2 * a + 1 - type;
        }
        return a - sz;
    }

    template< typename C >
    int find_first(int a, const C &check) {
        Monoid L = M1;
        if(a <= 0) {
            if(check(f(L, seg[1]))) return find_subtree(1, check, L, false);
            return -1;
        }
        int b = sz;
        for(a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
            if(a & 1) {
                Monoid nxt = f(L, seg[a]);
                if(check(nxt)) return find_subtree(a, check, L, false);
                L = nxt;
                ++a;
            }
        }
        return -1;
    }

    template< typename C >
    int find_last(int b, const C &check) {
        Monoid R = M1;
        if(b >= sz) {
            if(check(f(seg[1], R))) return find_subtree(1, check, R, true);
            return -1;
        }
        int a = sz;
        for(b += sz; a < b; a >>= 1, b >>= 1) {
            if(b & 1) {
                Monoid nxt = f(seg[--b], R);
                if(check(nxt)) return find_subtree(b, check, R, true);
                R = nxt;
            }
        }
        return -1;
    }
};

template< typename Monoid, typename F >
SegmentTree< Monoid, F > get_segment_tree(int N, const F& f, const Monoid& M1) {
    return {N, f, M1};
}

signed main(){
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout.setf(ios_base::fixed);
    cout.precision(12);

    int n, m;
    cin >> n >> m;

    assert(1 <= n && n <= 150000);
    assert(1 <= m && m <= n);

    vector<int> a(n), v(n);

    for (int i = 0; i < n; ++i) {
        cin >> a[i] >> v[i];
        assert(1 <= a[i] && a[i] <= m);
        assert(-10000 <= v[i] && v[i] <= 10000);
    }

    auto seg = get_segment_tree(n + 1, [](int a, int b) { return (max(a, b)); }, 0);

    for (int i = 0; i < n; ++i) {
        seg.update(a[i], max(seg[a[i]], max(seg.query(0, a[i]), seg.query(a[i] + 1, n + 1)) + v[i]));
    }

    cout << seg.query(0, n + 1) << '\n';

    return (0);
}
accuracy: 1
time_ms: 30
memory_kb: 6256
final_rank: 1

code_snippet: #include <bits/stdc++.h>
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define drep(i,j,n) for(int i=0;i<(int)(n-1);i++)for(int j=i+1;j<(int)(n);j++)
#define trep(i,j,k,n) for(int i=0;i<(int)(n-2);i++)for(int j=i+1;j<(int)(n-1);j++)for(int k=j+1;k<(int)(n);k++)
#define codefor int test;scanf("%d",&test);while(test--)
#define INT(...) int __VA_ARGS__;in(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__;in(__VA_ARGS__)
#define yes(ans) if(ans)printf("yes\n");else printf("no\n")
#define Yes(ans) if(ans)printf("Yes\n");else printf("No\n")
#define YES(ans) if(ans)printf("YES\n");else printf("NO\n")
#define popcount(v) __builtin_popcountll(v)
#define vector2d(type,name,h,...) vector<vector<type>>name(h,vector<type>(__VA_ARGS__))
#define vector3d(type,name,h,w,...) vector<vector<vector<type>>>name(h,vector<vector<type>>(w,vector<type>(__VA_ARGS__)))
#define vector4d(type,name,h,w,d,...) vector<vector<vector<vector<type>>>>name(h,vector<vector<vector<type>>>(w,vector<vector<type>>(d,vector<type>(__VA_ARGS__))))
using namespace std;
using ll = long long;
template<class T> using rpriority_queue = priority_queue<T, vector<T>, greater<T>>;
const int MOD=1000000007;
const int MOD2=998244353;
const int INF=1<<30;
const ll INF2=1LL<<60;
void scan(int& a){scanf("%d",&a);}
void scan(long long& a){scanf("%lld",&a);}
template<class T,class L>void scan(pair<T, L>& p){scan(p.first);scan(p.second);}
template<class T,class U,class V>void scan(tuple<T,U,V>& p){scan(get<0>(p));scan(get<1>(p));scan(get<2>(p));}
template<class T, size_t size> void scan(array<T, size>& a){ for(auto&& i : a) scan(i);}
template<class T> void scan(T& a){cin>>a;}
template<class T> void scan(vector<T>& vec){for(auto&& it:vec)scan(it);}
void in(){}
template <class Head, class... Tail> void in(Head& head, Tail&... tail){scan(head);in(tail...);}
void print(const int& a){printf("%d",a);}
void print(const long long& a){printf("%lld",a);}
void print(const double& a){printf("%.15lf",a);}
template<class T,class L>void print(const pair<T, L>& p){print(p.first);putchar(' ');print(p.second);}
template<class T> void print(const T& a){cout<<a;}
template<class T> void print(const vector<T>& vec){if(vec.empty())return;print(vec[0]);for(auto it=vec.begin();++it!= vec.end();){putchar(' ');print(*it);}}
void out(){putchar('\n');}
template<class T> void out(const T& t){print(t);putchar('\n');}
template <class Head, class... Tail> void out(const Head& head,const Tail&... tail){print(head);putchar(' ');out(tail...);}
template<class T> void dprint(const T& a){cerr<<a;}
template<class T> void dprint(const vector<T>& vec){if(vec.empty())return;cerr<<vec[0];for(auto it=vec.begin();++it!= vec.end();){cerr<<" "<<*it;}}
void debug(){cerr<<endl;}
template<class T> void debug(const T& t){dprint(t);cerr<<endl;}
template <class Head, class... Tail> void debug(const Head& head, const Tail&... tail){dprint(head);cerr<<" ";debug(tail...);}
ll intpow(ll a, ll b){ ll ans = 1; while(b){ if(b & 1) ans *= a; a *= a; b /= 2; } return ans; }
ll modpow(ll a, ll b, ll p){ ll ans = 1; while(b){ if(b & 1) (ans *= a) %= p; (a *= a) %= p; b /= 2; } return ans; }
ll modinv(ll a, ll m) {ll b = m, u = 1, v = 0;while (b) {ll t = a / b;a -= t * b; swap(a, b);u -= t * v; swap(u, v);}u %= m;if (u < 0) u += m;return u;}
ll updivide(ll a,ll b){return (a+b-1)/b;}
int msb(ll v){return 63-__builtin_clzll(v);}
template<class T> void chmax(T &a,const T b){if(b>a)a=b;}
template<class T> void chmin(T &a,const T b){if(b<a)a=b;}


template <class S, S (*op)(S, S), S (*e)()> struct segtree {
  public:
    segtree() : segtree(0) {}
    segtree(int n) : segtree(std::vector<S>(n, e())) {}
    segtree(const std::vector<S>& v) : _n(int(v.size())) {
        log = ceil_pow2(_n);
        size = 1 << log;
        d = std::vector<S>(2 * size, e());
        for (int i = 0; i < _n; i++) d[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }

    void set(int p, S x) {
        assert(0 <= p && p < _n);
        p += size;
        d[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }

    S get(int p) {
        assert(0 <= p && p < _n);
        return d[p + size];
    }
    const S operator[](int p) const { return get(p); }
    S operator[](int p) { return get(p); }

    S prod(int l, int r) {
        assert(0 <= l && l <= r && r <= _n);
        S sml = e(), smr = e();
        l += size;
        r += size;

        while (l < r) {
            if (l & 1) sml = op(sml, d[l++]);
            if (r & 1) smr = op(d[--r], smr);
            l >>= 1;
            r >>= 1;
        }
        return op(sml, smr);
    }

    S all_prod() { return d[1]; }

    template <bool (*f)(S)> int max_right(int l) {
        return max_right(l, [](S x) { return f(x); });
    }
    template <class F> int max_right(int l, F f) {
        assert(0 <= l && l <= _n);
        assert(f(e()));
        if (l == _n) return _n;
        l += size;
        S sm = e();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!f(op(sm, d[l]))) {
                while (l < size) {
                    l = (2 * l);
                    if (f(op(sm, d[l]))) {
                        sm = op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }

    template <bool (*f)(S)> int min_left(int r) {
        return min_left(r, [](S x) { return f(x); });
    }
    template <class F> int min_left(int r, F f) {
        assert(0 <= r && r <= _n);
        assert(f(e()));
        if (r == 0) return 0;
        r += size;
        S sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!f(op(d[r], sm))) {
                while (r < size) {
                    r = (2 * r + 1);
                    if (f(op(d[r], sm))) {
                        sm = op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while ((r & -r) != r);
        return 0;
    }

  private:
    int _n, size, log;
    std::vector<S> d;
    int ceil_pow2(int n) {
        int x = 0;
        while ((1U << x) < (unsigned int)(n)) x++;
        return x;
    }
    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
};

int op(int a,int b){return max(a,b);}
int e(){return 0;}

int main(){
    INT(n,m);
    vector<array<int,2>> a(n);
    segtree<int,op,e> seg(m);
    rep(i,n){
        in(a[i][0],a[i][1]);
        a[i][0]--;
        int v=max(seg.prod(0,a[i][0]),seg.prod(a[i][0]+1,m));
        seg.set(a[i][0],max(seg[a[i][0]],v+a[i][1]));
    }
    out(seg.all_prod());
}
accuracy: 1
time_ms: 30
memory_kb: 6832
final_rank: 3