Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

Range Sum Query 2D - เปลี่ยนแปลงได้ใน C++


สมมติว่าเรามีเมทริกซ์ 2 มิติที่เรียกว่าเมทริกซ์ เราต้องคำนวณผลรวมขององค์ประกอบภายในสี่เหลี่ยมผืนผ้าที่กำหนดโดยมุมซ้ายบนและมุมขวาล่าง

ดังนั้นหากอินพุตเป็นแบบ

3 0 1 4 2
5 6 3 2 1
1 2 0 1 5
4 1 0 1 7
1 0 3 0 5

ดังนั้นจะเป็นวิธีการหาผลรวมอัพเดทค่าถ้าเราเรียกมันว่า

sumRegion(2, 1, 4, 3)

อัปเดต(3, 2, 2)

sumRegion(2, 1, 4, 3) ,

จากนั้นผลลัพธ์จะเป็น 8 และ 10 เนื่องจากสี่เหลี่ยมผืนผ้าด้านบน (ที่มีสีเขียว) ถูกกำหนดโดย (2,1) และ (4, 3) ซึ่งมีผลรวม =8

เพื่อแก้ปัญหานี้ เราจะทำตามขั้นตอนเหล่านี้ -

  • กำหนดแผนผังอาร์เรย์ 2 มิติหนึ่งรายการ

  • กำหนดค่าอาร์เรย์ 2 มิติหนึ่งค่า

  • กำหนดตัวเริ่มต้นที่ใช้เมทริกซ์เป็นอินพุต

  • n :=ขนาดแถวของเมทริกซ์

  • m :=(ถ้าไม่ใช่ n ไม่เป็นศูนย์ แสดงว่าเป็น 0 มิฉะนั้น ขนาด col ของเมทริกซ์)

  • ค่า :=กำหนดอาร์เรย์ 2 มิติหนึ่งขนาด n x m

  • tree :=กำหนดอาร์เรย์ 2 มิติของคำสั่ง (n + 1) x (m + 1)

  • สำหรับการเริ่มต้น i :=0 เมื่อ i − n อัปเดต (เพิ่ม i ขึ้น 1) ทำ −

    • สำหรับการเริ่มต้น j :=0 เมื่อ j

      • อัปเดต (i, j, matrix[i, j])

  • กำหนดฟังก์ชัน update() จะใช้ row, col, val,

  • ถ้า n เท่ากับ 0 หรือ m เท่ากับ 0 แล้ว −

    • กลับ

  • delta :=val - ค่า[แถว, col]

  • value[row, col] :=val

  • สำหรับการเริ่มต้น i :=แถว + 1 เมื่อ i <=n อัปเดต i :=i + i &(-i) ทำ -

    • สำหรับการเริ่มต้น j :=col + 1 เมื่อ j <=m อัปเดต j :=j + j &(-j) do -

      • tree[i, j] :=tree[i, j] + เดลต้า

  • กำหนดฟังก์ชัน sum() ซึ่งจะใช้แถว col

  • ยกเลิก :=0

  • สำหรับการเริ่มต้น i :=row เมื่อ i> 0, update i :=i - i &(-i), do −

    • สำหรับการเริ่มต้น j :=col เมื่อ j> 0, อัปเดต j :=j - j &(-j) ทำ −

      • ret :=ret + tree[i, j]

  • รีเทิร์น

  • กำหนดฟังก์ชัน sumRegion() ซึ่งจะใช้ row1, col1, row2, col2,

  • ถ้า m เท่ากับ 0 หรือ n เท่ากับ 0 แล้ว −

    • คืนค่า 0

  • (เพิ่มแถวที่ 2 ขึ้น 1)

  • (เพิ่มแถวที่ 1 ขึ้น 1)

  • (เพิ่ม col1 โดย 1)

  • (เพิ่ม col2 ขึ้น 1)

  • ผลตอบแทนรวม(row2, col2) + sum(row1 - 1, col1 - 1) - sum(row1 - 1, col2) - sum(row2, col1 - 1)

ตัวอย่าง

ให้เราดูการใช้งานต่อไปนี้เพื่อความเข้าใจที่ดีขึ้น -

#include <bits/stdc++.h>
using namespace std;
class NumMatrix {
public:
   int n, m;
   vector<vector<int>> tree;
   vector<vector<int>> value;
   NumMatrix(vector<vector<int>> &matrix) {
      n = matrix.size();
      m = !n ? 0 : matrix[0].size();
      value = vector<vector<int>>(n, vector<int>(m));
      tree = vector<vector<int>>(n + 1, vector<int>(m + 1));
      for (int i = 0; i < n; i++) {
         for (int j = 0; j < m; j++) {
            update(i, j, matrix[i][j]);
         }
      }
   }
   void update(int row, int col, int val) {
      if (n == 0 || m == 0)
         return;
      int delta = val - value[row][col];
      value[row][col] = val;
      for (int i = row + 1; i <= n; i += i & (-i)) {
         for (int j = col + 1; j <= m; j += j & (-j)) {
            tree[i][j] += delta;
         }
      }
   }
   int sum(int row, int col) {
      int ret = 0;
      for (int i = row; i > 0; i -= i & (-i)) {
         for (int j = col; j > 0; j -= j & (-j)) {
            ret += tree[i][j];
         }
      }
      return ret;
   }
   int sumRegion(int row1, int col1, int row2, int col2) {
      if (m == 0 || n == 0)
         return 0;
      row2++;
      row1++;
      col1++;
      col2++;
      return sum(row2, col2) + sum(row1 - 1, col1 - 1) - sum(row1 - 1, col2) - sum(row2, col1 - 1);
   }
};
main() {
   vector<vector<int>> v = {
      {3, 0, 1, 4, 2},
      {5, 6, 3, 2, 1},
      {1, 2, 0, 1, 5},
      {4, 1, 0, 1, 7},
      {1, 0, 3, 0, 5}};
   NumMatrix ob(v);
   cout << (ob.sumRegion(2, 1, 4, 3)) << endl;
   ob.update(3, 2, 2);
   cout << (ob.sumRegion(2, 1, 4, 3)) << endl;
}

อินพุต

vector<vector<int>> v = {
   {3, 0, 1, 4, 2},
   {5, 6, 3, 2, 1},
   {1, 2, 0, 1, 5},
   {4, 1, 0, 1, 7},
   {1, 0, 3, 0, 5}};
NumMatrix ob(v);
cout << (ob.sumRegion(2, 1, 4, 3)) << endl;
ob.update(3, 2, 2);
cout << (ob.sumRegion(2, 1, 4, 3)) << endl;

ผลลัพธ์

8
10