← Home
package main

import (
	"fmt"
	"io"
	"os"
)

var buffer []byte
var bufIdx, bufLen int

func readByte() byte {
	if bufIdx >= bufLen {
		if buffer == nil {
			buffer = make([]byte, 65536)
		}
		n, err := os.Stdin.Read(buffer)
		if err != nil && err != io.EOF {
			panic(err)
		}
		if n == 0 {
			return 0
		}
		bufIdx = 0
		bufLen = n
	}
	b := buffer[bufIdx]
	bufIdx++
	return b
}

func readInt() int {
	b := readByte()
	for b > 0 && b <= ' ' {
		b = readByte()
	}
	if b == 0 {
		return 0
	}
	res := 0
	for b > ' ' {
		res = res*10 + int(b-'0')
		b = readByte()
	}
	return res
}

func main() {
	n := readInt()
	if n == 0 {
		return
	}
	m := readInt()

	a_t := make([][]int, m)
	for c := 0; c < m; c++ {
		a_t[c] = make([]int, n)
	}
	for r := 0; r < n; r++ {
		for c := 0; c < m; c++ {
			a_t[c][r] = readInt()
		}
	}

	first_dup := make([][]int, n)
	seen_r := make([]int, 160005)
	cv_fd := 0
	for i1 := 0; i1 < n; i1++ {
		first_dup[i1] = make([]int, m)
		for c := 0; c < m; c++ {
			cv_fd++
			fd := n
			col := a_t[c]
			for r := i1; r < n; r++ {
				v := col[r]
				if seen_r[v] == cv_fd {
					fd = r
					break
				}
				seen_r[v] = cv_fd
			}
			first_dup[i1][c] = fd
		}
	}

	max_area := 0
	seen := make([]uint32, 160005)
	current_version := 0

	for i1 := 0; i1 < n; i1++ {
		if (n-i1)*m <= max_area {
			break
		}
		for i2 := i1; i2 < n; i2++ {
			h := i2 - i1 + 1
			if h*m <= max_area {
				continue
			}

			max_consec := 0
			consec := 0
			for c := 0; c < m; c++ {
				if first_dup[i1][c] > i2 {
					consec++
					if consec > max_consec {
						max_consec = consec
					}
				} else {
					consec = 0
				}
			}
			if h*max_consec <= max_area {
				continue
			}

			current_version++
			cv_shifted := uint32(current_version) << 10
			limit := 0

			_ = a_t[m-1]

			for c := 0; c < m; c++ {
				if h*(m-limit) <= max_area {
					break
				}

				val_to_store := cv_shifted | uint32(c+1)
				col := a_t[c]
				_ = col[i2]

				for r := i1; r <= i2; r++ {
					v := col[r]
					s := seen[v]
					seen[v] = val_to_store
					if s > cv_shifted {
						ls := int(s & 1023)
						if ls > limit {
							limit = ls
						}
					}
				}
				cand := h * (c - limit + 1)
				if cand > max_area {
					max_area = cand
				}
			}
		}
	}

	fmt.Println(max_area)
}