diff --git a/.travis.yml b/.travis.yml index 2a28131..1a5fc88 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,9 @@ language: crystal before_install: - sudo apt-get -qq update - sudo apt-get install -y ruby default-jdk haskell-platform python3 + - curl -s "https://get.sdkman.io" | bash + - source "$HOME/.sdkman/bin/sdkman-init.sh" + - sdk install kotlin install: make clean build diff --git a/Makefile b/Makefile index 0ba9231..06852f4 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ build: g++ -O2 main.cpp -o $(BIN_DIR)/cpp javac -d $(BIN_DIR) Main.java ghc -O2 main.hs -outputdir=$(BUILD_DIR) -o $(BIN_DIR)/haskell + kotlinc main.kt -include-runtime -d $(BIN_DIR)/kotlin.jar test: mkdir $(TMP_DIR) @@ -32,4 +33,6 @@ test: @cmp $(TMP_DIR)/crystal.out $(TMP_DIR)/haskell.out || (echo "Failed: Haskell" && exit 1) python3 main.py < $(TMP_DIR)/test_data.in > $(TMP_DIR)/python3.out @cmp $(TMP_DIR)/crystal.out $(TMP_DIR)/python3.out || (echo "Failed: Python3" && exit 1) + java -jar $(BIN_DIR)/kotlin.jar < $(TMP_DIR)/test_data.in > $(TMP_DIR)/kotlin.out + @cmp $(TMP_DIR)/crystal.out $(TMP_DIR)/kotlin.out || (echo "Failed: Kotlin" && exit 1) @echo "Passed" diff --git a/README.md b/README.md index 6d2d23f..b0f17ec 100644 --- a/README.md +++ b/README.md @@ -80,3 +80,4 @@ Your output should consist of a single line for each test case containing n numb - [scps940707](https://github.com/scps940707) YyWang - Java - [sifmelcara](https://github.com/sifmelcara) mingchuan - Haskell - [chuanchan1116](https://github.com/chuanchan1116) William Tsai - Python 3 +- [david50407](https://github.com/david50407) David Kuo - Kotlin diff --git a/main.kt b/main.kt new file mode 100644 index 0000000..1b1c38e --- /dev/null +++ b/main.kt @@ -0,0 +1,89 @@ +import java.util.Scanner + +const val THRESHOLD = 60 + +fun main(args: Array) { + val reader = Scanner(System.`in`) + + while (true) { + val n: Int = reader.nextInt() + if (n == 0) break + + var ranks = IntArray(n) + var points = ArrayList() + repeat(n) { i -> + points.add(Point(i, reader.nextInt(), reader.nextInt())) + } + + points.sort() + + findRank(ranks, points) + + println(ranks.joinToString(separator = " ")) + } + + reader.close() +} + +fun MutableList.insertFrom(index: Int, to: Int) { + if (index == to) return + val tmp = this[index] + this.removeAt(index) + this.add(if (index > to) to else to - 1, tmp) +} + +fun findRank(ranks: IntArray, points: MutableList) : List { + if (points.size <= 1) return points + if (points.size <= THRESHOLD) { + repeat(points.size) { + if (it == 0) return@repeat + + val currentPoint = points[it] + if (currentPoint.y < points[0].y) { + points.insertFrom(it, to = 0) + return@repeat + } + + var i = it + while (true) { + if (currentPoint.y >= points[i - 1].y) break; + --i + } + points.insertFrom(it, to = i) + ranks[currentPoint.i] += i + } + return ArrayList(points) + } + + val leftPoints = findRank(ranks, points.subList(0, points.size / 2)) + val rightPoints = findRank(ranks, points.subList(points.size / 2, points.size)) + var resultPoints = ArrayList() + + var l: Int = 0 + var r: Int = 0 + while (true) { + if (leftPoints[l].y <= rightPoints[r].y) { + resultPoints.add(leftPoints[l++]) + if (l == leftPoints.size) { + rightPoints.listIterator(r).forEach { + ranks[it.i] += l + resultPoints.add(it) + } + break + } + } else { + resultPoints.add(rightPoints[r]) + ranks[rightPoints[r++].i] += l + if (r == rightPoints.size) { + resultPoints.addAll(leftPoints.subList(l, leftPoints.size)) + break + } + } + } + + return resultPoints +} + +data class Point(val i: Int, val x: Int = 0, val y: Int = 0) : Comparable { + override fun compareTo(other: Point) : Int = if (this.x == other.x) this.y.compareTo(other.y) else this.x.compareTo(other.x) +}