二维树状数组
根据题意,我们很自然的想到,需要一个支持在二维数组中进行区间更新和单点查询的数据结构。
因此可以使用二维树状数组求解。
注:本题使用二维差分的做法更优,请参考灵神的题解。
P.S. 抱歉之前的描述有误,我用的二维树状数组而不是线段树。
代码
###Python3
#二维树状数组,维护区域和
class SegmentTree2D:
def __init__(self, n, m):
self.n = n
self.m = m
self.tree = [[0] * (m + 1) for _ in range(n + 1)]
def lowbit(self, x):
return x & (-x)
def update(self, x, y, val):
while x <= self.n:
y1 = y
while y1 <= self.m:
self.tree[x][y1] += val
y1 += self.lowbit(y1)
x += self.lowbit(x)
def query(self, x, y):
res = 0
while x > 0:
y1 = y
while y1 > 0:
res += self.tree[x][y1]
y1 -= self.lowbit(y1)
x -= self.lowbit(x)
return res
class Solution:
def rangeAddQueries(self, n: int, queries: List[List[int]]) -> List[List[int]]:
seg = SegmentTree2D(n, n)
for x1, y1, x2, y2 in queries:
seg.update(x1 + 1, y1 + 1, 1)
seg.update(x2 + 2, y1 + 1, -1)
seg.update(x1 + 1, y2 + 2, -1)
seg.update(x2 + 2, y2 + 2, 1)
res = [[0] * n for _ in range(n)]
for i in range(n):
for j in range(n):
res[i][j] = seg.query(i + 1, j + 1)
return res
###C++
#include<bits/stdc++.h>
using namespace std;
class SegmentTree2D{
public:
int n, m;
vector<vector<int>> tree;
SegmentTree2D(int n, int m): n(n), m(m), tree(n + 1, vector<int>(m + 1, 0)){}
int lowbit(int x){
return x & (-x);
}
void update(int x, int y, int val){
while(x <= n){
int y1 = y;
while(y1 <= m){
tree[x][y1] += val;
y1 += lowbit(y1);
}
x += lowbit(x);
}
}
int query(int x, int y){
int res = 0;
while(x > 0){
int y1 = y;
while(y1 > 0){
res += tree[x][y1];
y1 -= lowbit(y1);
}
x -= lowbit(x);
}
return res;
}
};
class Solution {
public:
vector<vector<int>> rangeAddQueries(int n, vector<vector<int>>& queries) {
SegmentTree2D seg(n, n);
for(auto& q: queries){
seg.update(q[0] + 1, q[1] + 1, 1);
seg.update(q[2] + 2, q[1] + 1, -1);
seg.update(q[0] + 1, q[3] + 2, -1);
seg.update(q[2] + 2, q[3] + 2, 1);
}
vector<vector<int>> res(n, vector<int>(n, 0));
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
res[i][j] = seg.query(i + 1, j + 1);
}
}
return res;
}
};
###C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct SegmentTree2D{
int n, m;
int **tree;
} SegmentTree2D;
int lowbit(int x){
return x & (-x);
}
void update(SegmentTree2D *seg, int x, int y, int val){
while(x <= seg->n){
int y1 = y;
while(y1 <= seg->m){
seg->tree[x][y1] += val;
y1 += lowbit(y1);
}
x += lowbit(x);
}
}
int query(SegmentTree2D *seg, int x, int y){
int res = 0;
while(x > 0){
int y1 = y;
while(y1 > 0){
res += seg->tree[x][y1];
y1 -= lowbit(y1);
}
x -= lowbit(x);
}
return res;
}
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
int** rangeAddQueries(int n, int** queries, int queriesSize, int* queriesColSize, int* returnSize, int** returnColumnSizes){
SegmentTree2D *seg = (SegmentTree2D *)malloc(sizeof(SegmentTree2D));
seg->n = n;
seg->m = n;
seg->tree = (int **)malloc(sizeof(int *) * (n + 1));
for(int i = 0; i <= n; i++){
seg->tree[i] = (int *)malloc(sizeof(int) * (n + 1));
memset(seg->tree[i], 0, sizeof(int) * (n + 1));
}
for(int i = 0; i < queriesSize; i++){
update(seg, queries[i][0] + 1, queries[i][1] + 1, 1);
update(seg, queries[i][2] + 2, queries[i][1] + 1, -1);
update(seg, queries[i][0] + 1, queries[i][3] + 2, -1);
update(seg, queries[i][2] + 2, queries[i][3] + 2, 1);
}
int **res = (int **)malloc(sizeof(int *) * n);
for(int i = 0; i < n; i++){
res[i] = (int *)malloc(sizeof(int) * n);
for(int j = 0; j < n; j++){
res[i][j] = query(seg, i + 1, j + 1);
}
}
*returnSize = n;
*returnColumnSizes = (int *)malloc(sizeof(int) * n);
for(int i = 0; i < n; i++){
(*returnColumnSizes)[i] = n;
}
return res;
}
###Java
//二维树状数组
class SegmentTree2D{
int n, m;
int[][] tree;
public SegmentTree2D(int n, int m){
this.n = n;
this.m = m;
tree = new int[n + 1][m + 1];
}
int lowbit(int x){
return x & (-x);
}
void update(int x, int y, int val){
while(x <= n){
int y1 = y;
while(y1 <= m){
tree[x][y1] += val;
y1 += lowbit(y1);
}
x += lowbit(x);
}
}
int query(int x, int y){
int res = 0;
while(x > 0){
int y1 = y;
while(y1 > 0){
res += tree[x][y1];
y1 -= lowbit(y1);
}
x -= lowbit(x);
}
return res;
}
};
class Solution {
public int[][] rangeAddQueries(int n, int[][] queries) {
SegmentTree2D seg = new SegmentTree2D(n, n);
for(int[] q: queries){
seg.update(q[0] + 1, q[1] + 1, 1);
seg.update(q[2] + 2, q[1] + 1, -1);
seg.update(q[0] + 1, q[3] + 2, -1);
seg.update(q[2] + 2, q[3] + 2, 1);
}
int[][] res = new int[n][n];
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
res[i][j] = seg.query(i + 1, j + 1);
}
}
return res;
}
}
###Javascript
// #二维树状数组,维护区域和
class SegmentTree2D {
constructor(n, m) {
this.n = n;
this.m = m;
this.tree = new Array(n + 1).fill(0).map(() => new Array(m + 1).fill(0));
}
lowbit(x) {
return x & (-x);
}
update(x, y, val) {
while (x <= this.n) {
let y1 = y;
while (y1 <= this.m) {
this.tree[x][y1] += val;
y1 += this.lowbit(y1);
}
x += this.lowbit(x);
}
}
query(x, y) {
let res = 0;
while (x > 0) {
let y1 = y;
while (y1 > 0) {
res += this.tree[x][y1];
y1 -= this.lowbit(y1);
}
x -= this.lowbit(x);
}
return res;
}
}
/**
* @param {number} n
* @param {number[][]} queries
* @return {number[][]}
*/
var rangeAddQueries = function(n, queries) {
let seg = new SegmentTree2D(n, n);
for (let [x1, y1, x2, y2] of queries) {
seg.update(x1 + 1, y1 + 1, 1);
seg.update(x2 + 2, y1 + 1, -1);
seg.update(x1 + 1, y2 + 2, -1);
seg.update(x2 + 2, y2 + 2, 1);
}
let res = new Array(n).fill(0).map(() => new Array(n).fill(0));
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
res[i][j] = seg.query(i + 1, j + 1);
}
}
return res;
};
###Go
package main
type SegmentTree2D struct {
n, m int
tree [][]int
}
func lowbit(x int) int {
return x & (-x)
}
func update(seg *SegmentTree2D, x, y, val int) {
for x <= seg.n {
y1 := y
for y1 <= seg.m {
seg.tree[x][y1] += val
y1 += lowbit(y1)
}
x += lowbit(x)
}
}
func query(seg *SegmentTree2D, x, y int) int {
res := 0
for x > 0 {
y1 := y
for y1 > 0 {
res += seg.tree[x][y1]
y1 -= lowbit(y1)
}
x -= lowbit(x)
}
return res
}
func rangeAddQueries(n int, queries [][]int) [][]int {
seg := &SegmentTree2D{
n: n,
m: n,
tree: make([][]int, n+1),
}
for i := 0; i <= n; i++ {
seg.tree[i] = make([]int, n+1)
}
for _, query := range queries {
update(seg, query[0]+1, query[1]+1, 1)
update(seg, query[2]+2, query[1]+1, -1)
update(seg, query[0]+1, query[3]+2, -1)
update(seg, query[2]+2, query[3]+2, 1)
}
res := make([][]int, n)
for i := 0; i < n; i++ {
res[i] = make([]int, n)
for j := 0; j < n; j++ {
res[i][j] = query(seg, i+1, j+1)
}
}
return res
}
###Rust
use std::cmp::min;
struct SegmentTree2D {
n: usize,
m: usize,
tree: Vec<Vec<i32>>,
}
impl SegmentTree2D {
fn new(n: usize, m: usize) -> Self {
let mut tree = vec![vec![0; m + 1]; n + 1];
SegmentTree2D { n, m, tree }
}
fn lowbit(&self, x: usize) -> usize {
x & (!x + 1)
}
fn update(&mut self, x: usize, y: usize, val: i32) {
let mut x = x;
while x <= self.n {
let mut y1 = y;
while y1 <= self.m {
self.tree[x][y1] += val;
y1 += self.lowbit(y1);
}
x += self.lowbit(x);
}
}
fn query(&self, x: usize, y: usize) -> i32 {
let mut res = 0;
let mut x = x;
while x > 0 {
let mut y1 = y;
while y1 > 0 {
res += self.tree[x][y1];
y1 -= self.lowbit(y1);
}
x -= self.lowbit(x);
}
res
}
}
impl Solution {
pub fn range_add_queries(n: i32, queries: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
let mut seg = SegmentTree2D::new(n as usize, n as usize);
for query in queries {
seg.update(query[0] as usize + 1, query[1] as usize + 1, 1);
seg.update(query[2] as usize + 2, query[1] as usize + 1, -1);
seg.update(query[0] as usize + 1, query[3] as usize + 2, -1);
seg.update(query[2] as usize + 2, query[3] as usize + 2, 1);
}
let mut res = vec![vec![0; n as usize]; n as usize];
for i in 0..n as usize {
for j in 0..n as usize {
res[i][j] = seg.query(i + 1, j + 1);
}
}
res
}
}
###Swift
class SegmentTree2D {
var n: Int
var m: Int
var tree: [[Int]]
init(n: Int, m: Int) {
self.n = n
self.m = m
self.tree = Array(repeating: Array(repeating: 0, count: m + 1), count: n + 1)
}
func lowbit(_ x: Int) -> Int {
return x & (-x)
}
func update(_ x: Int, _ y: Int, _ val: Int) {
var x = x
while x <= n {
var y1 = y
while y1 <= m {
tree[x][y1] += val
y1 += lowbit(y1)
}
x += lowbit(x)
}
}
func query(_ x: Int, _ y: Int) -> Int {
var res = 0
var x = x
while x > 0 {
var y1 = y
while y1 > 0 {
res += tree[x][y1]
y1 -= lowbit(y1)
}
x -= lowbit(x)
}
return res
}
}
class Solution {
func rangeAddQueries(_ n: Int, _ queries: [[Int]]) -> [[Int]] {
let seg = SegmentTree2D(n: n, m: n)
for q in queries {
seg.update(q[0] + 1, q[1] + 1, 1)
seg.update(q[2] + 2, q[1] + 1, -1)
seg.update(q[0] + 1, q[3] + 2, -1)
seg.update(q[2] + 2, q[3] + 2, 1)
}
var res = Array(repeating: Array(repeating: 0, count: n), count: n)
for i in 0..<n {
for j in 0..<n {
res[i][j] = seg.query(i + 1, j + 1)
}
}
return res
}
}
###Kotlin
class SegmentTree2D {
val n: Int
val m: Int
val tree: Array<IntArray>
constructor(n: Int, m: Int) {
this.n = n
this.m = m
tree = Array(n + 1) { IntArray(m + 1) }
}
fun lowbit(x: Int): Int {
return x and (-x)
}
fun update(x: Int, y: Int, `val`: Int) {
var x = x
while (x <= n) {
var y1 = y
while (y1 <= m) {
tree[x][y1] += `val`
y1 += lowbit(y1)
}
x += lowbit(x)
}
}
fun query(x: Int, y: Int): Int {
var res = 0
var x = x
while (x > 0) {
var y1 = y
while (y1 > 0) {
res += tree[x][y1]
y1 -= lowbit(y1)
}
x -= lowbit(x)
}
return res
}
}
class Solution {
fun rangeAddQueries(n: Int, queries: Array<IntArray>): Array<IntArray> {
val seg = SegmentTree2D(n, n)
for (q in queries) {
seg.update(q[0] + 1, q[1] + 1, 1)
seg.update(q[2] + 2, q[1] + 1, -1)
seg.update(q[0] + 1, q[3] + 2, -1)
seg.update(q[2] + 2, q[3] + 2, 1)
}
val res = Array(n) { IntArray(n) }
for (i in 0 until n) {
for (j in 0 until n) {
res[i][j] = seg.query(i + 1, j + 1)
}
}
return res
}
}
###TypeScript
class SegmentTree2D {
n: number;
m: number;
tree: number[][];
constructor(n: number, m: number) {
this.n = n;
this.m = m;
this.tree = new Array(n + 1).fill(0).map(() => new Array(m + 1).fill(0));
}
lowbit(x: number): number {
return x & (-x);
}
update(x: number, y: number, val: number): void {
while (x <= this.n) {
let y1 = y;
while (y1 <= this.m) {
this.tree[x][y1] += val;
y1 += this.lowbit(y1);
}
x += this.lowbit(x);
}
}
query(x: number, y: number): number {
let res = 0;
while (x > 0) {
let y1 = y;
while (y1 > 0) {
res += this.tree[x][y1];
y1 -= this.lowbit(y1);
}
x -= this.lowbit(x);
}
return res;
}
}
function rangeAddQueries(n: number, queries: number[][]): number[][] {
const seg = new SegmentTree2D(n, n);
for (const query of queries) {
seg.update(query[0] + 1, query[1] + 1, 1);
seg.update(query[2] + 2, query[1] + 1, -1);
seg.update(query[0] + 1, query[3] + 2, -1);
seg.update(query[2] + 2, query[3] + 2, 1);
}
const res: number[][] = new Array(n).fill(0).map(() => new Array(n).fill(0));
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
res[i][j] = seg.query(i + 1, j + 1);
}
}
return res;
};
###C#
class SegmentTree2D{
int n, m;
int[,] tree;
public SegmentTree2D(int n, int m){
this.n = n;
this.m = m;
tree = new int[n + 1,m + 1];
}
public int lowbit(int x){
return x & (-x);
}
public void update(int x, int y, int val){
while(x <= n){
int y1 = y;
while(y1 <= m){
tree[x,y1] += val;
y1 += lowbit(y1);
}
x += lowbit(x);
}
}
public int query(int x, int y){
int res = 0;
while(x > 0){
int y1 = y;
while(y1 > 0){
res += tree[x,y1];
y1 -= lowbit(y1);
}
x -= lowbit(x);
}
return res;
}
};
public class Solution {
public int[][] RangeAddQueries(int n, int[][] queries) {
SegmentTree2D seg = new SegmentTree2D(n, n);
foreach(int[] q in queries){
seg.update(q[0] + 1, q[1] + 1, 1);
seg.update(q[2] + 2, q[1] + 1, -1);
seg.update(q[0] + 1, q[3] + 2, -1);
seg.update(q[2] + 2, q[3] + 2, 1);
}
int[][] res = new int[n][];
for(int i = 0; i < n; i++){
res[i] = new int[n];
for(int j = 0; j < n; j++){
res[i][j] = seg.query(i + 1, j + 1);
}
}
return res;
}
}
时间复杂度:$O(Q \times \log(N^2) + N^2 \times \log(N^2))$。其中Q是查询次数,N是二维数组的宽度和高度。
空间复杂度:$O(N^2)$。
各语言执行用时(Java最快,Python最慢):
{:width=400}