* @param {number} N
* @param {number[][]} lamps
* @param {number[][]} queries
* @return {number[]}
* 首先理解清楚题意: 任何一盏灯, 都能照亮穿过它的水平、垂直、左上到右下(135度角,主
对角线)线、右上到左下(45度角, 副对角线)线这四条线途经的任意格子, 但是每次查询, 只
会关掉包括被查询点在内离它最近的这四条线经过的9个格子里的灯。
* 要看某个格子亮不亮, 那就看经过这个格子的四条线有没有途经亮着灯的格子(自己也算)。我
们发现,同一条垂直线上的格子水平坐标(x)相同, 同一
条水平线上的格子纵坐标(y)相同;同一条45度角线上的格子x + y相同,同一条135度角线上的
格子x - y相同;四种类别里每一种类别内不是同一条线上的格子,值一定不同。
* 所以我们初始时只需要分别统计网格内这四类线(每一类线都有多条不同的线)每一条线有多
少盏灯亮着,然后没查询一次先根据统计信息判断被查询的格子亮不亮,然后再在四类线条统计
信息里面减去要熄灭的灯
就行;每查询一次就进行一次先判断亮不亮、再灭灯的操作,一次进行就行了。
* 注意了:网格最多有10 ** 9 格, 我们用到的最大数是 2 * (10 ** 9) - 1,js最大整数是
2 ** 53次方, 是没有数值溢出的
* */
// 坐标水平最大值是 10 ** 9 - 1
const rowLen = 10 ** 9
var gridIllumination = function(N, lamps, queries) {
// y
const rowCounts = new Map()
// x
const colCounts = new Map()
const deg45Counts = new Map()
const deg135Counts = new Map()
// 统计每盏灯的位置上, 有灯的格子才进行关灯操作,没灯的格子不能进行管等操作
const lampPosition = new Set()
// 统计每条线上有多少盏灯
for(let lamp of lamps) {
mapAddOne(rowCounts, lamp[0])
mapAddOne(colCounts, lamp[1])
mapAddOne(deg45Counts, lamp[0] + lamp[1])
mapAddOne(deg135Counts, lamp[0] - lamp[1])
lampPosition.add(lamp[0] * rowLen + lamp[1])
}
// 计算结果
const ans = new Array(queries.length)
for(let i = 0; i < queries.length; i++) {
const q = queries[i]
const deg45 = q[0] + q[1]
const deg135 = q[0] - q[1]
if(mapHas(rowCounts, q[0]) || mapHas(colCounts, q[1]) || mapHas(deg45Counts, deg45) || mapHas(deg135Counts, deg135)) {
ans[i] = 1
closeLamp(rowCounts, colCounts, deg45Counts, deg135Counts, q[0], q[1], lampPosition)
} else ans[i] = 0
}
return ans
};
function mapAddOne(map, key) {
if(map.has(key)) {
map.set(key, map.get(key) + 1)
} else map.set(key, 1)
}
function mapHas(map, key) {
if(map.has(key) && (map.get(key) > 0)) {
return true
} else return false
}
function mapReduceOne(map, key) {
if(map.has(key)) {
map.set(key, map.get(key) - 1)
}
}
function closeLamp(rowCounts, colCounts, deg45Counts, deg135Counts, row, col, lampPosition) {
for(let r = -1; r <=1; r++) {
for(let c = -1; c <= 1; c++) {
const r2 = row + r
const c2 = col + c
// 不能越界
if((r2 < 0) || (r2 >= rowLen) || (c2 < 0) ||(c2 >= rowLen)) continue
// 有灯才关灯, 没灯就不能关
const lamp = r2 * rowLen + c2
if(lampPosition.has(lamp)) {
lampPosition.delete(lamp)
mapReduceOne(rowCounts, r2)
mapReduceOne(colCounts, c2)
mapReduceOne(deg45Counts, r2 + c2)
mapReduceOne(deg135Counts, r2 - c2)
}
}
}
}```