[R20D]矩阵移位
- 难度 提高
- 时限 1s
- 空限 512m
- 模拟
数据规模:,,,矩阵内仅含大写字母。
思路
矩阵规模和操作次数都极小(,),直接逐次模拟即可。唯一的「坑」是 高达 ,但循环移位只需考虑 对长度的余数。
- 操作类型 1(行右移 次):对每一行
l..r,将长度 的行数组整体右移 位。设余数为 ,则新行new[j] = old[(j + m - km) % m](把原本在位置j-km的字符搬到j)。 - 操作类型 2(列下移 次):对每一列
l..r,把该列从上到下收集成一个长度 的临时数组,整体下移 位,即new[i] = old[(i + n - kn) % n],再写回矩阵。
时该行/列无需移动,直接跳过,省去一次复制。
复杂度
每次操作最多遍历 个元素, 次操作总计 ,远在时限之内。
仓颉实现
import std.convert.*
import std.env.*
main(): Int64 {
let reader = getStdIn()
let first = reader.readln().getOrThrow().split(" ", removeEmpty: true)
let n = Int64.parse(first[0])
let m = Int64.parse(first[1])
let nn = n
let mm = m
var grid = Array<Array<Rune>>(nn, { _: Int64 => Array<Rune>(mm, { _: Int64 => r'A' }) })
for (i in 0..nn) {
grid[i] = reader.readln().getOrThrow().toRuneArray()
}
let Q = Int64.parse(reader.readln().getOrThrow())
for (_ in 0..Q) {
let parts = reader.readln().getOrThrow().split(" ", removeEmpty: true)
let typ = Int64.parse(parts[0])
let l = Int64.parse(parts[1])
let r = Int64.parse(parts[2])
let k = Int64.parse(parts[3])
if (typ == 1) {
// 行 l..r 右循环移位 k
let km = k % mm
if (km != 0) {
for (i in (l - 1)..r) {
let old = grid[i]
var newrow = Array<Rune>(mm, { _: Int64 => r'A' })
for (j in 0..mm) {
newrow[j] = old[(j + mm - km) % mm]
}
grid[i] = newrow
}
}
} else {
// 列 l..r 下循环移位 k
let kn = k % nn
if (kn != 0) {
for (j in (l - 1)..r) {
var old = Array<Rune>(nn, { _: Int64 => r'A' })
for (t in 0..nn) {
old[t] = grid[t][j]
}
for (i in 0..nn) {
grid[i][j] = old[(i + nn - kn) % nn]
}
}
}
}
}
let sb = StringBuilder()
for (i in 0..nn) {
for (j in 0..mm) {
sb.append(grid[i][j])
}
sb.append("\n")
}
print(sb.toString())
return 0
}