```go
package main
import (
"fmt"
"sort"
)
const MOD = 998244353
type SegTree struct {
tree []int64
lazy []int64
hasLazy []bool
n int
mod int64
}
func NewSegTree(nn int, mmod int64) *SegTree {
return &SegTree{
tree: make([]int64, 4*(nn+1)),
lazy: make([]int64, 4*(nn+1)),
hasLazy: make([]bool, 4*(nn+1)),
n: nn,
mod: mmod,
}
}
func (s *SegTree) push(node, start, end int) {
if s.hasLazy[node] {
s.tree[node] = int64(end-start+1) * s.lazy[node] % s.mod
if start != end {
s.lazy[2*node] = s.lazy[node]
s.hasLazy[2*node] = true
s.lazy[2*node+1] = s.lazy[node]
s.hasLazy[2*node+1] = true
}
s.hasLazy[node] = false
}
}
func (s *SegTree) updateRange(node, start, end, l, r int, val int64) {
s.push(node, start, end)
if start > end || start > r || end < l {
return
}
if l <= start && end <= r {
s.lazy[node] = val
s.hasLazy[node] = true
s.push(node, start, end)
return
}
mid := (start + end) / 2
s.updateRange(2*node, start, mid, l, r, val)
s.updateRange(2*node+1, mid+1, end, l, r, val)
s.tree[node] = (s.tree[2*node] + s.tree[2*node+1]) % s.mod
}
func (s *SegTree) updatePoint(node, start, end, idx int, val int64) {
s.push(node, start, end)
if start > end || start > idx || end < idx {
return
}
if start == end {
s.tree[node] = val % s.mod
return
}
mid := (start + end) / 2
if idx <= mid {
s.updatePoint(2*node, start, mid, idx, val)
} else {
s.updatePoint(2*node+1, mid+1, end, idx, val)
}
s.tree[node] = (s.tree[2*node] + s.tree[2*node+1]) % s.mod
}
func (s *SegTree) getQuery(node, start, end, l, r int) int64 {
s.push(node, start, end)
if start > end || start > r || end < l {
return 0
}
if l <= start && end <= r {
return s.tree[node]
}
mid := (start + end) / 2
return (s.getQuery(2*node, start, mid, l, r) + s.getQuery(2*node+1, mid+1, end, l, r)) % s.mod
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func main() {
var n, k, m int
fmt.Scan(&n, &k, &m)
ls := make([]int, m)
rs := make([]int, m)
xs := make([]int, m)
for i := 0; i < m; i++ {
fmt.Scan(&ls[i], &rs[i], &xs[i])
}
ans := int64(1)
for bit := 0; bit < k; bit++ {
diff := make([]int, n+2)
for j := 0; j < m; j++ {
if (xs[j] & (1 << bit)) != 0 {
diff[ls[j]]++
diff[rs[j]+1]--
}
}
forced1 := make([]bool, n+2)
pre := 0
for i := 1; i <= n; i++ {
pre += diff[i]
forced1[i] = pre > 0
}
var free_pos []int
for i := 1; i <= n; i++ {
if !forced1[i] {
free_pos = append(free_pos, i)
}
}
qq := len(free_pos)
var force0 [][2]int
for j := 0; j < m; j++ {
if (xs[j] & (1 << bit)) == 0 {
force0 = append(force0, [2]int{ls[j], rs[j]})
}
}
possible := true
for _, seg := range force0 {
ll := seg[0]
rr := seg[1]
it := sort.Search(len(free_pos), func(k int) bool { return free_pos[k] >= ll })
if it < len(free_pos) && free_pos[it] <= rr {
continue
}
possible = false
break
}
var ways int64
if possible {
st := NewSegTree(qq, MOD)
st.updatePoint(1, 0, qq, 0, 1)
maxSt := make([]int, qq+2)
for _, seg := range force0 {
ll := seg[0]
rr := seg[1]
itlow := sort.Search(len(free_pos), func(k int) bool { return free_pos[k] >= ll })
if itlow >= len(free_pos) || free_pos[itlow] > rr {
continue
}
ithigh := sort.Search(len(free_pos), func(k int) bool { return free_pos[k] > rr }) - 1
left_idx := itlow + 1
right_idx := ithigh + 1
if left_idx > right_idx {
continue
}
maxSt[right_idx] = max(maxSt[right_idx], left_idx)
}
for ii := 1; ii <= qq; ii++ {
pp := maxSt[ii]
total_prev := st.getQuery(1, 0, qq, 0, ii-1)
st.updateRange(1, 0, qq, 0, pp-1, 0)
st.updatePoint(1, 0, qq, ii, total_prev)
}
ways = st.getQuery(1, 0, qq, 0, qq)
}
ans = (ans * ways) % MOD
}
fmt.Println(ans)
}
```