← Home
```go
package main

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

// Global IO
var reader *bufio.Reader
var writer *bufio.Writer

func printf(f string, a ...interface{}) { fmt.Fprintf(writer, f, a...) }

type Video struct {
	l, r, id int
}

type Channel struct {
	a, b, c, id int
}

func main() {
	reader = bufio.NewReader(os.Stdin)
	writer = bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)

	scanInt := func() int {
		scanner.Scan()
		txt := scanner.Text()
		val := 0
		for _, ch := range txt {
			val = val*10 + int(ch-'0')
		}
		return val
	}

	if !scanner.Scan() {
		return
	}
	nVal := 0
	for _, ch := range scanner.Text() {
		nVal = nVal*10 + int(ch-'0')
	}
	n := nVal
	m := scanInt()

	videos := make([]Video, n)
	for i := 0; i < n; i++ {
		videos[i] = Video{l: scanInt(), r: scanInt(), id: i + 1}
	}

	channels := make([]Channel, m)
	for i := 0; i < m; i++ {
		channels[i] = Channel{a: scanInt(), b: scanInt(), c: scanInt(), id: i + 1}
	}

	bestEff := int64(-1)
	bestV := -1
	bestC := -1

	update := func(eff int64, v, c int) {
		if eff > bestEff {
			bestEff = eff
			bestV = v
			bestC = c
		}
	}

	// Phase 1: Left Anchored (l_i <= a_j)
	solveLeftAnchored(n, m, videos, channels, update)

	// Phase 2: Right Anchored (r_i >= b_j) - via coordinate reversal
	const C = 1000000000
	revVideos := make([]Video, n)
	for i := 0; i < n; i++ {
		revVideos[i] = Video{l: C - videos[i].r, r: C - videos[i].l, id: videos[i].id}
	}
	revChannels := make([]Channel, m)
	for i := 0; i < m; i++ {
		revChannels[i] = Channel{a: C - channels[i].b, b: C - channels[i].a, c: channels[i].c, id: channels[i].id}
	}
	solveLeftAnchored(n, m, revVideos, revChannels, update)

	// Phase 3: Inside (a_j <= l_i <= r_i <= b_j)
	solveInside(n, m, videos, channels, update)

	if bestEff <= 0 {
		printf("0\n")
	} else {
		printf("%d\n", bestEff)
		printf("%d %d\n", bestV, bestC)
	}
}

func solveLeftAnchored(n, m int, vs []Video, cs []Channel, update func(int64, int, int)) {
	vSorted := make([]Video, n)
	copy(vSorted, vs)
	sort.Slice(vSorted, func(i, j int) bool {
		return vSorted[i].l < vSorted[j].l
	})

	cSorted := make([]Channel, m)
	copy(cSorted, cs)
	sort.Slice(cSorted, func(i, j int) bool {
		return cSorted[i].a < cSorted[j].a
	})

	vIdx := 0
	maxR := -1
	maxRIdx := -1

	for _, ch := range cSorted {
		for vIdx < n && vSorted[vIdx].l <= ch.a {
			if vSorted[vIdx].r > maxR {
				maxR = vSorted[vIdx].r
				maxRIdx = vSorted[vIdx].id
			}
			vIdx++
		}

		if maxRIdx != -1 {
			end := maxR
			if ch.b < end {
				end = ch.b
			}
			start := ch.a
			if end > start {
				eff := int64(end-start) * int64(ch.c)
				update(eff, maxRIdx, ch.id)
			}
		}
	}
}

type SegNode struct {
	val, id int
}

type SegTree struct {
	size int
	tree []SegNode
}

func newSegTree(sz int) *SegTree {
	n := 1
	for n < sz {
		n *= 2
	}
	st := &SegTree{size: n, tree: make([]SegNode, 2*n)}
	for i := range st.tree {
		st.tree[i] = SegNode{-1, -1}
	}
	return st
}

func (st *SegTree) update(pos, val, id int) {
	idx := pos + st.size
	if val > st.tree[idx].val {
		st.tree[idx] = SegNode{val, id}
	}
	for idx > 1 {
		idx /= 2
		left := st.tree[2*idx]
		right := st.tree[2*idx+1]
		if left.val >= right.val {
			st.tree[idx] = left
		} else {
			st.tree[idx] = right
		}
	}
}

func (st *SegTree) query(l, r int) (int, int) {
	l += st.size
	r += st.size
	resVal := -1
	resId := -1

	for l < r {
		if l%2 == 1 {
			if st.tree[l].val > resVal {
				resVal = st.tree[l].val
				resId = st.tree[l].id
			}
			l++
		}
		if r%2 == 1 {
			r--
			if st.tree[r].val > resVal {
				resVal = st.tree[r].val
				resId = st.tree[r].id
			}
		}
		l /= 2
		r /= 2
	}
	return resVal, resId
}

func solveInside(n, m int, vs []Video, cs []Channel, update func(int64, int, int)) {
	coords := make([]int, 0, n+m)
	for _, v := range vs {
		coords = append(coords, v.l)
	}
	for _, c := range cs {
		coords = append(coords, c.a)
	}
	sort.Ints(coords)
	uniqueCoords := make([]int, 0, len(coords))
	if len(coords) > 0 {
		uniqueCoords = append(uniqueCoords, coords[0])
		for i := 1; i < len(coords); i++ {
			if coords[i] != coords[i-1] {
				uniqueCoords = append(uniqueCoords, coords[i])
			}
		}
	}

	rank := func(x int) int {
		return sort.SearchInts(uniqueCoords, x)
	}

	st := newSegTree(len(uniqueCoords))

	type Event struct {
		pos   int
		kind  int 
		index int
	}

	events := make([]Event, 0, n+m)
	for i := range vs {
		events = append(events, Event{pos: vs[i].r, kind: 0, index: i})
	}
	for i := range cs {
		events = append(events, Event{pos: cs[i].b, kind: 1, index: i})
	}

	sort.Slice(events, func(i, j int) bool {
		if events[i].pos != events[j].pos {
			return events[i].pos < events[j].pos
		}
		return events[i].kind < events[j].kind
	})

	for _, e := range events {
		if e.kind == 0 {
			v := vs[e.index]
			length := v.r - v.l
			rPos := rank(v.l)
			st.update(rPos, length, v.id)
		} else {
			c := cs[e.index]
			rPos := rank(c.a)
			maxLen, vId := st.query(rPos, len(uniqueCoords))
			if vId != -1 {
				eff := int64(maxLen) * int64(c.c)
				update(eff, vId, c.id)
			}
		}
	}
}
```