```go
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
)
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() {
scanner := bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanWords)
buf := make([]byte, 1024*1024)
scanner.Buffer(buf, 10*1024*1024)
nextInt64 := func() int64 {
scanner.Scan()
v, _ := strconv.ParseInt(scanner.Text(), 10, 64)
return v
}
nextInt := func() int {
scanner.Scan()
v, _ := strconv.Atoi(scanner.Text())
return v
}
writer := bufio.NewWriter(os.Stdout)
defer writer.Flush()
if !scanner.Scan() {
return
}
t, _ := strconv.Atoi(scanner.Text())
for ; t > 0; t-- {
n := nextInt()
a := make([]int64, n)
for i := 0; i < n; i++ {
a[i] = nextInt64()
}
A := make([]int64, n+1)
A[0] = 0
for i := 1; i <= n; i++ {
if i%2 == 1 {
A[i] = A[i-1] - a[i-1]
} else {
A[i] = A[i-1] + a[i-1]
}
}
minTree := make([]int64, 4*(n+1))
maxTree := make([]int64, 4*(n+1))
const INF int64 = 3e18
const NINF int64 = -3e18
var build func(node, l, r int)
build = func(node, l, r int) {
if l == r {
if l%2 == 0 {
minTree[node] = A[l]
maxTree[node] = NINF
} else {
minTree[node] = INF
maxTree[node] = A[l]
}
return
}
mid := (l + r) / 2
build(2*node, l, mid)
build(2*node+1, mid+1, r)
minTree[node] = min(minTree[2*node], minTree[2*node+1])
maxTree[node] = max(maxTree[2*node], maxTree[2*node+1])
}
build(1, 0, n)
var queryMin func(node, l, r, ql, qr int, val int64) int
queryMin = func(node, l, r, ql, qr int, val int64) int {
if l > qr || r < ql || minTree[node] >= val {
return -1
}
if l == r {
return l
}
mid := (l + r) / 2
res := queryMin(2*node, l, mid, ql, qr, val)
if res != -1 {
return res
}
return queryMin(2*node+1, mid+1, r, ql, qr, val)
}
var queryMax func(node, l, r, ql, qr int, val int64) int
queryMax = func(node, l, r, ql, qr int, val int64) int {
if l > qr || r < ql || maxTree[node] <= val {
return -1
}
if l == r {
return l
}
mid := (l + r) / 2
res := queryMax(2*node, l, mid, ql, qr, val)
if res != -1 {
return res
}
return queryMax(2*node+1, mid+1, r, ql, qr, val)
}
sortedA := make([]int64, n+1)
copy(sortedA, A)
sort.Slice(sortedA, func(i, j int) bool { return sortedA[i] < sortedA[j] })
var unq []int64
for i := 0; i <= n; i++ {
if i == 0 || sortedA[i] != sortedA[i-1] {
unq = append(unq, sortedA[i])
}
}
getID := func(val int64) int {
l, r := 0, len(unq)-1
for l <= r {
mid := (l + r) / 2
if unq[mid] == val {
return mid
} else if unq[mid] < val {
l = mid + 1
} else {
r = mid - 1
}
}
return -1
}
pos := make([][]int, len(unq))
for i, v := range A {
id := getID(v)
pos[id] = append(pos[id], i)
}
var total int64 = 0
for i := 0; i <= n; i++ {
val := A[i]
lim1 := n + 1
if i < n {
r1 := queryMin(1, 0, n, i+1, n, val)
if r1 != -1 {
lim1 = r1
}
}
lim2 := n + 1
if i < n {
r2 := queryMax(1, 0, n, i+1, n, val)
if r2 != -1 {
lim2 = r2
}
}
lim := lim1
if lim2 < lim {
lim = lim2
}
id := getID(val)
indices := pos[id]
leftIdx := sort.Search(len(indices), func(k int) bool { return indices[k] > i })
rightIdx := sort.Search(len(indices), func(k int) bool { return indices[k] >= lim })
total += int64(rightIdx - leftIdx)
}
fmt.Fprintln(writer, total)
}
}
```