← Home
```go
package main

import (
	"bufio"
	"fmt"
	"os"
)

const MOD = 998244353

func power(base, exp int64) int64 {
	res := int64(1)
	base = (base % MOD + MOD) % MOD
	for exp > 0 {
		if exp%2 == 1 {
			res = (res * base) % MOD
		}
		base = (base * base) % MOD
		exp /= 2
	}
	return res
}

func modInverse(n int64) int64 {
	return power(n, MOD-2)
}

func add_poly(A, B []int64) []int64 {
	n := len(A)
	if len(B) > n {
		n = len(B)
	}
	res := make([]int64, n)
	for i := 0; i < n; i++ {
		a, b := int64(0), int64(0)
		if i < len(A) {
			a = A[i]
		}
		if i < len(B) {
			b = B[i]
		}
		res[i] = (a + b) % MOD
	}
	for len(res) > 1 && res[len(res)-1] == 0 {
		res = res[:len(res)-1]
	}
	return res
}

func mul_poly(A, B []int64) []int64 {
	if len(A) == 0 || len(B) == 0 {
		return []int64{0}
	}
	res := make([]int64, len(A)+len(B)-1)
	for i, a := range A {
		if a == 0 {
			continue
		}
		for j, b := range B {
			res[i+j] = (res[i+j] + a*b) % MOD
		}
	}
	return res
}

func eval_poly(P []int64, x int64) int64 {
	x = (x%MOD + MOD) % MOD
	res := int64(0)
	pow := int64(1)
	for _, c := range P {
		res = (res + c*pow) % MOD
		pow = (pow * x) % MOD
	}
	return res
}

func shift_poly_minus_1(P []int64) []int64 {
	res := make([]int64, len(P))
	for i, c := range P {
		if c == 0 {
			continue
		}
		term := []int64{1}
		bin := []int64{MOD - 1, 1}
		for k := 1; k <= i; k++ {
			term = mul_poly(term, bin)
		}
		for j, val := range term {
			res[j] = (res[j] + c*val) % MOD
		}
	}
	for len(res) > 1 && res[len(res)-1] == 0 {
		res = res[:len(res)-1]
	}
	return res
}

func interpolate(Y []int64) []int64 {
	N := len(Y) - 1
	Poly := []int64{0}
	for i := 0; i <= N; i++ {
		Term := []int64{Y[i]}
		for j := 0; j <= N; j++ {
			if i != j {
				diff := int64(i - j)
				inv := modInverse(diff)
				c0 := (-int64(j) * inv) % MOD
				if c0 < 0 {
					c0 += MOD
				}
				c1 := inv
				Term = mul_poly(Term, []int64{c0, c1})
			}
		}
		Poly = add_poly(Poly, Term)
	}
	return Poly
}

func sum_poly(P []int64) []int64 {
	D := len(P) - 1
	if D < 0 {
		return []int64{0}
	}
	pts := make([]int64, D+2)
	for x := 0; x <= D+1; x++ {
		pts[x] = eval_poly(P, int64(x))
	}
	S_pts := make([]int64, D+2)
	S_pts[0] = pts[0]
	for i := 1; i <= D+1; i++ {
		S_pts[i] = (S_pts[i-1] + pts[i]) % MOD
	}
	return interpolate(S_pts)
}

type Interval struct {
	L, R int64
	P    []int64
}

var intervals []Interval

func split_at(X int64) {
	for i := 0; i < len(intervals); i++ {
		iv := intervals[i]
		if iv.L < X && X <= iv.R {
			left := Interval{iv.L, X - 1, append([]int64(nil), iv.P...)}
			right := Interval{X, iv.R, append([]int64(nil), iv.P...)}
			intervals = append(intervals[:i], append([]Interval{left, right}, intervals[i+1:]...)...)
			break
		}
	}
}

func min(a, b int64) int64 {
	if a < b {
		return a
	}
	return b
}

func max(a, b int64) int64 {
	if a > b {
		return a
	}
	return b
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	var n int
	fmt.Fscan(reader, &n)
	var x int64
	fmt.Fscan(reader, &x)

	d := make([]int64, n)
	for i := 0; i < n; i++ {
		fmt.Fscan(reader, &d[i])
	}

	V := make([]int64, n+1)
	V[0] = x
	for i := 1; i <= n; i++ {
		V[i] = V[i-1] + d[i-1]
	}

	min_reach := make([]int64, n+1)
	max_reach := make([]int64, n+1)
	min_reach[0] = V[0]
	max_reach[0] = V[0]
	for i := 1; i <= n; i++ {
		min_reach[i] = min(min_reach[i-1], V[i])
		max_reach[i] = max(max_reach[i-1], V[i])
	}

	max_suff := make([]int64, n+1)
	max_suff[n] = V[n]
	for i := n - 1; i >= 0; i-- {
		max_suff[i] = max(max_suff[i+1], V[i])
	}

	M := int64(0)
	for i := 0; i <= n; i++ {
		diff := max_suff[i] - min_reach[i]
		if diff > M {
			M = diff
		}
	}

	type VRange struct {
		L, R int64
	}
	var v_ranges []VRange

	if V[0] <= max_reach[n]-M {
		v_ranges = append(v_ranges, VRange{V[0], max_reach[n] - M})
	}
	for k := 1; k <= n; k++ {
		if V[k] < min_reach[k-1] {
			L := V[k]
			R := min(min_reach[k-1]-1, max_suff[k]-M)
			if L <= R {
				v_ranges = append(v_ranges, VRange{L, R})
			}
		}
	}

	INF := int64(4000000000)
	intervals = []Interval{{-INF, INF, []int64{0}}}

	for _, vr := range v_ranges {
		split_at(vr.L)
		split_at(vr.R + 1)
		for i := 0; i < len(intervals); i++ {
			if intervals[i].L >= vr.L && intervals[i].R <= vr.R {
				intervals[i].P = []int64{1}
			}
		}
	}

	apply_inc := func(A, B int64) {
		split_at(A)
		split_at(B + 1)
		accum := int64(0)
		for i := 0; i < len(intervals); i++ {
			iv := intervals[i]
			if iv.L >= A && iv.R <= B {
				S := sum_poly(iv.P)
				S_L_minus_1 := eval_poly(S, iv.L-1)
				S_R := eval_poly(S, iv.R)

				const_term := (accum - S_L_minus_1) % MOD
				if const_term < 0 {
					const_term += MOD
				}
				intervals[i].P = add_poly(S, []int64{const_term})
				accum = (accum + S_R - S_L_minus_1) % MOD
				if accum < 0 {
					accum += MOD
				}
			}
		}
	}

	apply_dec := func(A, B int64) {
		type Shift struct {
			L, R int64
			P    []int64
		}
		var shifts []Shift
		for _, iv := range intervals {
			L_new := max(iv.L+1, A+1)
			R_new := min(iv.R+1, B+1)
			if L_new <= R_new {
				shifted_P := shift_poly_minus_1(iv.P)
				shifts = append(shifts, Shift{L_new, R_new, shifted_P})
			}
		}
		for _, sh := range shifts {
			split_at(sh.L)
			split_at(sh.R + 1)
			for i := 0; i < len(intervals); i++ {
				if intervals[i].L >= sh.L && intervals[i].R <= sh.R {
					intervals[i].P = add_poly(intervals[i].P, sh.P)
				}
			}
		}
	}

	apply_inc(V[0], V[0])

	for s := 1; s <= n; s++ {
		if d[s-1] > 0 {
			apply_inc(V[s-1]+1, V[s])
		} else {
			apply_dec(V[s], V[s-1]-1)
		}
	}

	ans := int64(0)
	for _, vr := range v_ranges {
		L_target := vr.L + M + 1
		R_target := vr.R + M + 1
		split_at(L_target)
		split_at(R_target + 1)
		for i := 0; i < len(intervals); i++ {
			if intervals[i].L >= L_target && intervals[i].R <= R_target {
				S := sum_poly(intervals[i].P)
				val := (eval_poly(S, intervals[i].R) - eval_poly(S, intervals[i].L-1)) % MOD
				if val < 0 {
					val += MOD
				}
				ans = (ans + val) % MOD
			}
		}
	}

	fmt.Printf("%d %d\n", M+1, ans)
}
```