← Home
For problem statement at 0-999/200-299/270-279/274/problemE.txt this is a correct solution, but verifier at 0-999/200-299/270-279/274/verifierE.go ends with case 1 failed: expected "15" got "17"
input:
8 10 4
7 6
6 8
1 6
4 6
8 2 NE
exit status 1 can you fix the verifier? ```go
package main

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

type Point struct {
	x, y int
}

type State struct {
	x, y, dx, dy int
}

type Segment struct {
	x1, y1, x2, y2, dx, dy int
}

type Interval struct {
	min, max int
}

type Event struct {
	U   int
	typ int // 1 for Add, 2 for Query, 3 for Remove
	V1  int
	V2  int
}

var bit []int

func add(idx, val int) {
	for ; idx < len(bit); idx += idx & -idx {
		bit[idx] += val
	}
}

func query(idx int) int {
	sum := 0
	for ; idx > 0; idx -= idx & -idx {
		sum += bit[idx]
	}
	return sum
}

func merge(intervals []Interval) []Interval {
	if len(intervals) == 0 {
		return nil
	}
	sort.Slice(intervals, func(i, j int) bool {
		return intervals[i].min < intervals[j].min
	})
	var merged []Interval
	curr := intervals[0]
	for i := 1; i < len(intervals); i++ {
		if intervals[i].min <= curr.max {
			if intervals[i].max > curr.max {
				curr.max = intervals[i].max
			}
		} else {
			merged = append(merged, curr)
			curr = intervals[i]
		}
	}
	merged = append(merged, curr)
	return merged
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	const maxCapacity = 2 * 1024 * 1024
	buf := make([]byte, maxCapacity)
	scanner.Buffer(buf, maxCapacity)
	scanner.Split(bufio.ScanWords)

	scanInt := func() int {
		scanner.Scan()
		n, _ := strconv.Atoi(scanner.Text())
		return n
	}

	scanString := func() string {
		scanner.Scan()
		return scanner.Text()
	}

	if !scanner.Scan() {
		return
	}
	n, _ := strconv.Atoi(scanner.Text())
	m := scanInt()
	k := scanInt()

	blockedSet := make(map[Point]bool)
	blocks0 := make(map[int][]int)
	blocks1 := make(map[int][]int)

	for i := 0; i < k; i++ {
		bx := scanInt()
		by := scanInt()
		blockedSet[Point{bx, by}] = true
		blocks0[bx-by] = append(blocks0[bx-by], bx)
		blocks1[bx+by] = append(blocks1[bx+by], bx)
	}

	for _, arr := range blocks0 {
		sort.Ints(arr)
	}
	for _, arr := range blocks1 {
		sort.Ints(arr)
	}

	xs := scanInt()
	ys := scanInt()
	dirStr := scanString()

	dx, dy := 0, 0
	switch dirStr {
	case "NE":
		dx, dy = -1, 1
	case "NW":
		dx, dy = -1, -1
	case "SE":
		dx, dy = 1, 1
	case "SW":
		dx, dy = 1, -1
	}

	isBlocked := func(cx, cy int) bool {
		if cx < 1 || cx > n || cy < 1 || cy > m {
			return true
		}
		return blockedSet[Point{cx, cy}]
	}

	getMinT := func(x, y, dx, dy int) int {
		dir := dx * dy
		var blocks map[int][]int
		if dir == 1 {
			blocks = blocks0
		} else {
			blocks = blocks1
		}

		C := x - dir*y
		tMin := n + m + 5

		tbx := x
		if dx == 1 {
			tbx = n + 1 - x
		}
		tby := y
		if dy == 1 {
			tby = m + 1 - y
		}
		if tbx < tMin {
			tMin = tbx
		}
		if tby < tMin {
			tMin = tby
		}

		lines := []int{C, C + dx, C - dx}
		for i, L := range lines {
			arr, ok := blocks[L]
			if !ok {
				continue
			}

			if dx == 1 {
				idx := sort.Search(len(arr), func(j int) bool {
					if i == 2 {
						return arr[j] >= x
					}
					return arr[j] > x
				})
				if idx < len(arr) {
					u := arr[idx]
					t := u - x
					if i == 2 {
						t++
					}
					if t < tMin {
						tMin = t
					}
				}
			} else {
				idx := sort.Search(len(arr), func(j int) bool {
					if i == 2 {
						return arr[j] > x
					}
					return arr[j] >= x
				})
				idx--
				if idx >= 0 {
					u := arr[idx]
					t := x - u
					if i == 2 {
						t++
					}
					if t < tMin {
						tMin = t
					}
				}
			}
		}
		return tMin
	}

	visitedStates := make(map[State]bool)
	var segments []Segment

	x, y := xs, ys
	for {
		state := State{x, y, dx, dy}
		if visitedStates[state] {
			break
		}
		visitedStates[state] = true

		t := getMinT(x, y, dx, dy)
		nx := x + (t-1)*dx
		ny := y + (t-1)*dy

		segments = append(segments, Segment{x, y, nx, ny, dx, dy})

		bx := isBlocked(nx+dx, ny)
		by := isBlocked(nx, ny+dy)
		bxy := isBlocked(nx+dx, ny+dy)

		var ndx, ndy int
		if bx && by {
			ndx, ndy = -dx, -dy
		} else if bx {
			ndx, ndy = -dx, dy
		} else if by {
			ndx, ndy = dx, -dy
		} else if bxy {
			ndx, ndy = -dx, -dy
		} else {
			ndx, ndy = dx, dy
		}

		x, y, dx, dy = nx, ny, ndx, ndy
	}

	horizMap := make(map[int][]Interval)
	vertMap := make(map[int][]Interval)

	for _, seg := range segments {
		U1 := seg.x1 + seg.y1
		U2 := seg.x2 + seg.y2
		V1 := seg.x1 - seg.y1
		V2 := seg.x2 - seg.y2

		if seg.dx*seg.dy == 1 {
			if U1 > U2 {
				U1, U2 = U2, U1
			}
			horizMap[V1] = append(horizMap[V1], Interval{U1, U2})
		} else {
			if V1 > V2 {
				V1, V2 = V2, V1
			}
			vertMap[U1] = append(vertMap[U1], Interval{V1, V2})
		}
	}

	var totalCells int64 = 0
	mergedHoriz := make(map[int][]Interval)
	for V, intervals := range horizMap {
		m := merge(intervals)
		mergedHoriz[V] = m
		for _, iv := range m {
			totalCells += int64((iv.max-iv.min)/2 + 1)
		}
	}

	mergedVert := make(map[int][]Interval)
	for U, intervals := range vertMap {
		m := merge(intervals)
		mergedVert[U] = m
		for _, iv := range m {
			totalCells += int64((iv.max-iv.min)/2 + 1)
		}
	}

	var events []Event
	for V, intervals := range mergedHoriz {
		for _, iv := range intervals {
			events = append(events, Event{U: iv.min, typ: 1, V1: V + 100005})
			events = append(events, Event{U: iv.max, typ: 3, V1: V + 100005})
		}
	}
	for U, intervals := range mergedVert {
		for _, iv := range intervals {
			events = append(events, Event{U: U, typ: 2, V1: iv.min + 100005, V2: iv.max + 100005})
		}
	}

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

	bit = make([]int, 300005)
	var intersections int64 = 0

	for _, ev := range events {
		if ev.typ == 1 {
			add(ev.V1, 1)
		} else if ev.typ == 3 {
			add(ev.V1, -1)
		} else if ev.typ == 2 {
			intersections += int64(query(ev.V2) - query(ev.V1-1))
		}
	}

	fmt.Println(totalCells - intersections)
}
```