ACM入门题-区间覆盖-Go语言
时间限制:C/C++ 1000MS,其他语言 2000MS
内存限制:C/C++ 256MB,其他语言 512MB
分数:100
描述
给定n个闭区间[ai; bi],其中 i=1,2,…,n。 这些区间的总和可以表示为闭合的成对非相交区间的总和。 我们要用最少的间隔找到这样的表示。 此表示的间隔应按升序写入输出。 我们说区间 [a; b] 和 [c; d] 是升序当且仅当 a <= b < c <= d。
输入一系列间隔的描述,计算满足上述条件的成对非相交区间,升序输出计算出的区间
输入描述
在输入的第一行有一个整数 n,3 <= n <= 50000。这是间隔数。 在第i+1行,1 <= i <= n,有区间[ai; bi] 形式为两个整数 ai 和 bi 由一个空格隔开,分别是区间的开始和结束,1 <= ai <= bi <= 1000000。
输出描述
输出应包含所有计算的成对非相交区间的描述。 在每一行中都应该写一个区间的描述。 它应该由两个整数组成,由一个空格隔开,分别是间隔的开始和结束。 间隔应按升序写入输出。
用例输入 1
5
5 6
1 4
10 10
6 9
8 10
用例输出 1
1 4
5 10
思路
这种方案不是最优解,但是理解起来不难。
- 先排序,如果左边界相同则按右边界排序。这里在Go语言里可以调用sort包
- 从小往大遍历,需要三个中间值来完成搜寻答案。这里左边界是单调递增的,可右边界可不一定,所有要记录它的最大值。
AC代码
package main
import (
"fmt"
"sort"
)
func main() {
var n, l, r int
fmt.Scan(&n)
grid := make([][]int, n)
ans := make([][]int, 0)
for i := 0; i < n; i++ {
fmt.Scan(&l, &r)
grid[i] = []int{l, r}
}
sort.Slice(grid, func(i, j int) bool { // 排序
if grid[i][0] < grid[j][0] {
return true
} else if grid[i][0] == grid[j][0] {
if grid[i][1] < grid[j][1] {
return true
} else {
return false
}
}
return false
})
var max = func(a, b int) int {
if a > b {
return a
}
return b
}
bg, ed, tmp := 0, 1, 0
for ed < n {
tmp = max(tmp, grid[ed-1][1])
if grid[ed][0] > tmp {
ans = append(ans, []int{grid[bg][0], tmp}) // 确定左右边界添加答案
bg = ed
}
ed++
}
ans = append(ans, []int{grid[bg][0], tmp})
for i := 0; i < len(ans); i++ {
fmt.Println(ans[i][0], ans[i][1])
}
}