```go
package main
import (
"bufio"
"fmt"
"os"
)
const inf int64 = 1e18
type SegmentTree struct {
tree []int64
lazy []int64
}
func NewSegmentTree(n int) *SegmentTree {
st := &SegmentTree{
tree: make([]int64, 4*n+1),
lazy: make([]int64, 4*n+1),
}
for i := range st.tree {
st.tree[i] = -inf
}
return st
}
func (st *SegmentTree) push(v int) {
if st.lazy[v] != 0 {
st.tree[2*v] += st.lazy[v]
st.lazy[2*v] += st.lazy[v]
st.tree[2*v+1] += st.lazy[v]
st.lazy[2*v+1] += st.lazy[v]
st.lazy[v] = 0
}
}
func (st *SegmentTree) update(v, tl, tr, l, r int, add int64) {
if l > r {
return
}
if l == tl && r == tr {
st.tree[v] += add
st.lazy[v] += add
} else {
st.push(v)
tm := (tl + tr) / 2
st.update(2*v, tl, tm, l, min(r, tm), add)
st.update(2*v+1, tm+1, tr, max(l, tm+1), r, add)
st.tree[v] = max64(st.tree[2*v], st.tree[2*v+1])
}
}
func (st *SegmentTree) set(v, tl, tr, pos int, val int64) {
if tl == tr {
st.tree[v] = val
st.lazy[v] = 0
} else {
st.push(v)
tm := (tl + tr) / 2
if pos <= tm {
st.set(2*v, tl, tm, pos, val)
} else {
st.set(2*v+1, tm+1, tr, pos, val)
}
st.tree[v] = max64(st.tree[2*v], st.tree[2*v+1])
}
}
func (st *SegmentTree) query(v, tl, tr, l, r int) int64 {
if l > r {
return -inf
}
if l == tl && r == tr {
return st.tree[v]
}
st.push(v)
tm := (tl + tr) / 2
return max64(
st.query(2*v, tl, tm, l, min(r, tm)),
st.query(2*v+1, tm+1, tr, max(l, tm+1), r),
)
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func max64(a, b int64) int64 {
if a > b {
return a
}
return b
}
type StackItem struct {
gapVal int64
start int
}
func main() {
reader := bufio.NewReader(os.Stdin)
writer := bufio.NewWriter(os.Stdout)
defer writer.Flush()
var n int
var a int64
fmt.Fscan(reader, &n, &a)
d := make([]int64, n+1)
c := make([]int64, n+1)
for i := 1; i <= n; i++ {
fmt.Fscan(reader, &d[i], &c[i])
}
st := NewSegmentTree(n)
stack := make([]StackItem, 0, n)
var currentS int64 = 0
var ans int64 = -inf
for i := 1; i <= n; i++ {
p := a - c[i]
sPrev := currentS
currentS += p
if i > 1 {
w := (d[i] - d[i-1]) * (d[i] - d[i-1])
currentEnd := i - 1
newStart := i - 1
for len(stack) > 0 {
top := stack[len(stack)-1]
if top.gapVal <= w {
stack = stack[:len(stack)-1]
st.update(1, 1, n, top.start, currentEnd, -(w - top.gapVal))
currentEnd = top.start - 1
newStart = top.start
} else {
break
}
}
stack = append(stack, StackItem{gapVal: w, start: newStart})
}
st.set(1, 1, n, i, -sPrev)
stack = append(stack, StackItem{gapVal: 0, start: i})
best := st.query(1, 1, n, 1, i)
if currentS+best > ans {
ans = currentS + best
}
}
fmt.Fprintln(writer, ans)
}
```