← Home
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)
}