package main
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
)
var scanner *bufio.Scanner
func init() {
scanner = bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanWords)
buf := make([]byte, 1024*1024)
scanner.Buffer(buf, 10*1024*1024)
}
func nextInt() int {
scanner.Scan()
res, _ := strconv.Atoi(scanner.Text())
return res
}
func nextInt64() int64 {
scanner.Scan()
res, _ := strconv.ParseInt(scanner.Text(), 10, 64)
return res
}
type Person struct {
id int
t int64
s int
f int
waiting bool
}
var tree []int
func add(node, l, r, idx, val int) {
if l == r {
tree[node] += val
return
}
mid := l + (r-l)/2
if idx <= mid {
add(2*node, l, mid, idx, val)
} else {
add(2*node+1, mid+1, r, idx, val)
}
tree[node] = tree[2*node] + tree[2*node+1]
}
func query(node, l, r, ql, qr int) int {
if ql > qr {
return 0
}
if l > qr || r < ql {
return 0
}
if ql <= l && r <= qr {
return tree[node]
}
mid := l + (r-l)/2
return query(2*node, l, mid, ql, qr) + query(2*node+1, mid+1, r, ql, qr)
}
func find_first(node, l, r, ql, qr int) int {
if ql > qr {
return -1
}
if l > qr || r < ql || tree[node] == 0 {
return -1
}
if l == r {
return l
}
mid := l + (r-l)/2
res := find_first(2*node, l, mid, ql, qr)
if res != -1 {
return res
}
return find_first(2*node+1, mid+1, r, ql, qr)
}
func find_last(node, l, r, ql, qr int) int {
if ql > qr {
return -1
}
if l > qr || r < ql || tree[node] == 0 {
return -1
}
if l == r {
return l
}
mid := l + (r-l)/2
res := find_last(2*node+1, mid+1, r, ql, qr)
if res != -1 {
return res
}
return find_last(2*node, l, mid, ql, qr)
}
func main() {
n := nextInt()
m := nextInt()
tree = make([]int, 4*m+4)
target_lists := make([][]int, m+1)
people := make([]Person, n)
sortedPeople := make([]*Person, n)
for i := 0; i < n; i++ {
people[i] = Person{
id: i,
t: nextInt64(),
s: nextInt(),
f: nextInt(),
waiting: true,
}
sortedPeople[i] = &people[i]
}
sort.Slice(sortedPeople, func(i, j int) bool {
return sortedPeople[i].t < sortedPeople[j].t
})
ans := make([]int64, n)
var active_targets int
var next_arr int
T := int64(0)
X := 1
for active_targets > 0 || next_arr < n {
for next_arr < n && sortedPeople[next_arr].t <= T {
p := sortedPeople[next_arr]
target_lists[p.s] = append(target_lists[p.s], p.id)
add(1, 1, m, p.s, 1)
active_targets++
next_arr++
}
if len(target_lists[X]) > 0 {
list := target_lists[X]
target_lists[X] = nil
for _, pid := range list {
add(1, 1, m, X, -1)
p := &people[pid]
if p.waiting {
p.waiting = false
target_lists[p.f] = append(target_lists[p.f], p.id)
add(1, 1, m, p.f, 1)
} else {
ans[p.id] = T
active_targets--
}
}
}
if active_targets == 0 {
if next_arr < n {
if T < sortedPeople[next_arr].t {
T = sortedPeople[next_arr].t
}
continue
} else {
break
}
}
pup := query(1, 1, m, X+1, m)
pdown := query(1, 1, m, 1, X-1)
var dir int
var Y int
if pup >= pdown {
dir = 1
Y = find_first(1, 1, m, X+1, m)
} else {
dir = -1
Y = find_last(1, 1, m, 1, X-1)
}
var dist int
if dir == 1 {
dist = Y - X
} else {
dist = X - Y
}
time_to_Y := T + int64(dist)
if next_arr < n && sortedPeople[next_arr].t < time_to_Y {
t_arr := sortedPeople[next_arr].t
dist_moved := int(t_arr - T)
X = X + dir*dist_moved
T = t_arr
} else {
X = Y
T = time_to_Y
}
}
out := bufio.NewWriter(os.Stdout)
defer out.Flush()
for i := 0; i < n; i++ {
fmt.Fprintln(out, ans[i])
}
}