package main
import (
"io"
"os"
"sort"
"strconv"
)
type Friend struct {
t int64
a int64
b int64
}
type Node struct {
l, r int
pr uint32
key int64
cnt int64
sz int64
sum int64
}
var nodes []Node
var seed uint64 = 88172645463393265
func rnd() uint32 {
seed ^= seed << 7
seed ^= seed >> 9
return uint32(seed)
}
func newNode(key, cnt int64) int {
nodes = append(nodes, Node{
key: key,
cnt: cnt,
sz: cnt,
sum: key * cnt,
pr: rnd(),
})
return len(nodes) - 1
}
func pull(x int) {
if x == 0 {
return
}
n := &nodes[x]
n.sz = n.cnt + nodes[n.l].sz + nodes[n.r].sz
n.sum = n.key*n.cnt + nodes[n.l].sum + nodes[n.r].sum
}
func rotateRight(x int) int {
y := nodes[x].l
nodes[x].l = nodes[y].r
nodes[y].r = x
pull(x)
pull(y)
return y
}
func rotateLeft(x int) int {
y := nodes[x].r
nodes[x].r = nodes[y].l
nodes[y].l = x
pull(x)
pull(y)
return y
}
func insert(x int, key, cnt int64) int {
if x == 0 {
return newNode(key, cnt)
}
if key == nodes[x].key {
nodes[x].cnt += cnt
pull(x)
return x
}
if key < nodes[x].key {
nodes[x].l = insert(nodes[x].l, key, cnt)
if nodes[x].l != 0 && nodes[nodes[x].l].pr > nodes[x].pr {
x = rotateRight(x)
}
} else {
nodes[x].r = insert(nodes[x].r, key, cnt)
if nodes[x].r != 0 && nodes[nodes[x].r].pr > nodes[x].pr {
x = rotateLeft(x)
}
}
pull(x)
return x
}
func removeSmallest(x int, k int64) (int, int64) {
if x == 0 || k == 0 {
return x, 0
}
l := nodes[x].l
if nodes[l].sz >= k {
nl, s := removeSmallest(l, k)
nodes[x].l = nl
pull(x)
return x, s
}
s := nodes[l].sum
k -= nodes[l].sz
nodes[x].l = 0
if nodes[x].cnt > k {
s += nodes[x].key * k
nodes[x].cnt -= k
pull(x)
return x, s
}
s += nodes[x].key * nodes[x].cnt
k -= nodes[x].cnt
nr, s2 := removeSmallest(nodes[x].r, k)
return nr, s + s2
}
func removeLargest(x int, k int64) (int, int64) {
if x == 0 || k == 0 {
return x, 0
}
r := nodes[x].r
if nodes[r].sz >= k {
nr, s := removeLargest(r, k)
nodes[x].r = nr
pull(x)
return x, s
}
s := nodes[r].sum
k -= nodes[r].sz
nodes[x].r = 0
if nodes[x].cnt > k {
s += nodes[x].key * k
nodes[x].cnt -= k
pull(x)
return x, s
}
s += nodes[x].key * nodes[x].cnt
k -= nodes[x].cnt
nl, s2 := removeLargest(nodes[x].l, k)
return nl, s + s2
}
func main() {
data, _ := io.ReadAll(os.Stdin)
p := 0
nextInt := func() int64 {
for p < len(data) && (data[p] < '0' || data[p] > '9') {
p++
}
var v int64
for p < len(data) && data[p] >= '0' && data[p] <= '9' {
v = v*10 + int64(data[p]-'0')
p++
}
return v
}
q := int(nextInt())
nodes = make([]Node, 1, 1200005)
out := make([]byte, 0, q*4)
for ; q > 0; q-- {
n := int(nextInt())
m := nextInt()
c := nextInt()
c0 := nextInt()
friends := make([]Friend, n)
for i := 0; i < n; i++ {
t := nextInt()
a := nextInt()
b := nextInt()
friends[i] = Friend{t: t, a: a, b: b}
}
if n > 1 {
sort.Slice(friends, func(i, j int) bool {
return friends[i].t < friends[j].t
})
}
times := make([]int64, 0, n)
bounds := make([]int, 0, n+1)
for i := 0; i < n; {
bounds = append(bounds, i)
t := friends[i].t
j := i + 1
for j < n && friends[j].t == t {
j++
}
times = append(times, t)
i = j
}
bounds = append(bounds, n)
k := len(times)
g := make([]int64, k+1)
prev := int64(0)
for i := 0; i < k; i++ {
g[i] = times[i] - prev
prev = times[i]
}
g[k] = m - prev
L := make([]int64, k+1)
if g[k] < c {
L[k] = g[k]
} else {
L[k] = c
}
for i := k - 1; i >= 0; i-- {
x := g[i] + L[i+1]
if x > c {
x = c
}
L[i] = x
}
root := 0
root = insert(root, 0, c0)
if nodes[root].sz > L[0] {
root, _ = removeLargest(root, nodes[root].sz-L[0])
}
ans := int64(0)
feasible := true
if nodes[root].sz < g[0] {
feasible = false
} else {
var s int64
root, s = removeSmallest(root, g[0])
ans += s
}
for i := 1; i <= k && feasible; i++ {
for j := bounds[i-1]; j < bounds[i]; j++ {
root = insert(root, friends[j].b, friends[j].a)
}
if nodes[root].sz > L[i] {
root, _ = removeLargest(root, nodes[root].sz-L[i])
}
if nodes[root].sz < g[i] {
feasible = false
break
}
var s int64
root, s = removeSmallest(root, g[i])
ans += s
}
if feasible {
out = strconv.AppendInt(out, ans, 10)
} else {
out = append(out, '-', '1')
}
out = append(out, '\n')
}
_, _ = os.Stdout.Write(out)
}