#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
#define int ll

#define REP(i,n) for(ll i=0;i<n;++i)
#define SORT(name) sort(name.begin(), name.end())
#define ZERO(p) memset(p, 0, sizeof(p))
#define MINUS(p) memset(p, -1, sizeof(p))
#if 0
#  define DBG(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#  define DBG(fmt, ...)
#endif

const ll LLINF = (1LL<<60);
const int INF = (1LL<<30);
const int MOD = 1000000007;
#define MAX_N 100010

ll N, C;
ll X[MAX_N] = {};
ll V[MAX_N] = {};

// 一次元累積和
// テンプレートであることに注意
template< typename T >
class CumulativeSum
{
public:
    vector< T > m_data;
    CumulativeSum() {};
    CumulativeSum(int sz) : m_data(sz, 0) {};

    // k に x を加える O(1)
    void Add(int k, int x) {
        assert(m_data.size() >= k);
        if(m_data.size() <= k) { m_data.push_back(x); }
        else { m_data[k] += x; }
    }

    // 累積和の構築 O(m_data.size())
    void Build() { for(int i = 1; i < m_data.size(); i++) { m_data[i] += m_data[i - 1]; } }

    // 区間 [0, k] の和を返す O(1)
    // 閉区間なので k が含まれることに注意
    T Query(int k) {
        if(k < 0) { return 0; }
        return (m_data[min(k, (int) m_data.size() - 1)]);
    }

    // 区間 [l, h] の和を返す O(1)
    // 閉区間なので k が含まれることに注意
    T Query(int l, int h) { return this->Query(h) - this->Query(l-1); }
};

template< typename Monoid >
class SegmentTree
{
    public:
        // モノイドを 2 つ引数に取リ、モノイドを返す関数
        using Func = function< Monoid(Monoid, Monoid) >;

    public:
        // セグ木を初期化します。
        // サイズは 10^6 くらいまでならいけそう
        // n  : セグ木のサイズ
        // f  : セグ木で判定する関数
        // M1 : 初期値(単位元)
        SegmentTree(int n, const Func f, const Monoid &M1) : m_F(f), m_M1(M1) {
            // 要素数は 2 のべき乗じゃないといけないのでそうする
            m_Size = 1;
            while(m_Size < n) { m_Size <<= 1; }
            m_Seg.assign(2 * m_Size, M1);
        }

        // k 番目の要素に x をセット (0-indexed)
        void Set(int k, const Monoid &x) { m_Seg[k + m_Size] = x; }

        // セグ木構築 O(N)
        void Build() {
            for(int k = m_Size - 1; k > 0; k--) {
                m_Seg[k] = m_F(m_Seg[2 * k + 0], m_Seg[2 * k + 1]);
            }
        }

        // k 番目の要素を x に変更する O(log N) (0-indexed)
        void Update(int k, const Monoid &x) {
            k += m_Size;
            m_Seg[k] = x;
            while(k >>= 1) {
                m_Seg[k] = m_F(m_Seg[2 * k + 0], m_Seg[2 * k + 1]);
            }
        }

        // 区間 [a, b) に対して初期設定した関数をした結果を返す O(log N)
        // 開区間なので b は含まれないので注意
        // 0-indexed
        Monoid Query(int a, int b) {
            Monoid l = m_M1, r = m_M1;
            for(a += m_Size, b += m_Size; a < b; a >>= 1, b >>= 1) {
                if(a & 1) l = m_F(l, m_Seg[a++]);
                if(b & 1) r = m_F(m_Seg[--b], r);
            }
            return m_F(l, r);
        }

        Monoid operator[](const int &k) const
        {
            return m_Seg[k + m_Size];
        }
    public:
        const Func m_F;            // このセグ木で処理する関数（二項演算）
        const Monoid m_M1;      // モノイドの初期値(単位元)

        int m_Size;             // セグ木の要素数
        vector< Monoid > m_Seg; // セグ木本体
};

signed main()
{
    CumulativeSum<ll> cs;

    cin >> N >> C;
    REP(i, N) {
        cin >> X[i] >> V[i];
        cs.Add(i, V[i]);
    }

    cs.Build();

    // 時計回りの区間 max
    SegmentTree<ll> cw_st(N, [](ll a, ll b){ return max(a, b); }, -1);
    // 反時計回りの区間 max
    SegmentTree<ll> ccw_st(N, [](ll a, ll b){ return max(a, b); }, -1);

    // 時計回りで一番効率が良いところ
    ll cw = 0;
    for(ll i = 0; i < N; ++i) {
        // X[i] まで行ったときの取得カロリー
        ll cal = cs.Query(0, i) - X[i];
        cw = max(cw, cal);
        cw_st.Set(i, cw);
    }
    // 反時計回りで一番効率が良いところ
    ll ccw = 0;
    for(ll i = N-1; i >= 0; --i) {
        ll cal = cs.Query(i, N-1) - (C - X[i]);
        ccw = max(ccw, cal);
        ccw_st.Set(i, ccw);
    }

    cw_st.Build();
    ccw_st.Build();

    // 時計回りで食べてからある地点で戻って一番効率が良いところ
    ll cw_r = 0;
    for(ll i = 0; i < N-1; ++i) {
        ll cal = cs.Query(0, i) - X[i] * 2;
        // そこから反時計回りで回る
        cal += ccw_st.Query(i+1, N);
        cw_r = max(cw_r, cal);
    }
    // 反時計回りで食べてからある地点で戻って一番効率が良いところ
    ll ccw_r = 0;
    for(ll i = N-1; i > 0; --i) {
        ll cal = cs.Query(i, N-1) - (C - X[i]) * 2;
        cal += cw_st.Query(0, i);
        ccw_r = max(ccw_r, cal);
    }

    DBG("cw:         %lld\n", cw);
    DBG("ccw:        %lld\n", ccw);
    DBG("cw_r:  %lld\n", cw_half_r);
    DBG("ccw_r: %lld\n", ccw_half_r);
    ll ans = max({cw, ccw, cw_r, ccw_r});
    printf("%lld\n", ans);

    return 0;
}


Measured memory_bytes: 6772