📜  使用BIT计算矩形空间中的三角形

📅  最后修改于: 2021-04-17 09:26:49             🧑  作者: Mango

前提条件:BIT(二叉索引树或Fenwick树),2D BIT
给定2D平面,响应Q查询,以下每种类型:

  1. 插入xy –插入点(x,y)坐标。
  2. Triangle x1 y1 x2 y2 –通过连接矩形内的点(由两个点(x1,y1)和(x2,y2)来描述),打印可以形成的三角形数量,其中(x1,y1)在左下角而(x2,y2)是右上角。我们将其表示为{(x1,y1),(x2,y2)}。(在答案中也包括面积为零的三角形)

例子:

In the red rectangle there are 6 points inserted, 
when each of them is joined with a line with every
other point, in all 20 triangles will be formed.

假设我们以某种方式拥有一种机制,可以找到给定矩形内的点数,在实例中,点数为’m’。
可以形成的三角形数为m C 3 (连接时每3个点将组成一个三角形);如果只计算退化的三角形,则必须减去面积为零或由同一条线上的点组成的三角形的数量。
现在,我们潜入该机制以查找矩形中的点数。假设我们有一种机制可以找到矩形内的点数。

Then number of points inside the rectangle 
{(x1, y1), (x2, y2)} are,

        P(x2, y2) - 
        P(x1 - 1, y2) - 
        P(x2, y1 - 1) + 
        P(x1 - 1, y1 - 1)

Where,
P(x, y) is number of triangles in rectangle
from (1, 1) to (x, y), i.e., {(1, 1), (x, y)}

现在,一旦找到一种找到P(x,y)的方法,就完成了。
如果首先进行所有插入查询,然后进行所有三角查询,那将是一件容易的事,我们可以维护一个2D表来存储点,而table [x] [y]将包含点的总数。矩形{(1,1),(x,y)}。
可以使用以下DP创建它:
table [x] [y] = table [x] [y – 1] + table [x – 1] [y] – table [x – 1] [y – 1]
或者我们可以使用2D BIT插入点并评估P(x,y)。有关2D BIT的可视化,请参见Top Coder。该图显示了一个16 * 8 2D BIT,并且在(5,3)处插入后的状态是蓝色节点,该节点被更新一次。
水平BIT对应于3,将1存储在索引3中,将1存储在索引4中,将1存储在索引8中;垂直表示对应于哪个水平BIT将接收该更新,而垂直表示则对应于5,因此从底部开始的第5个BIT将得到一个更新,第6个BIT,然后是第8个BIT,然后是第16个BIT。
让我们考虑一维BIT中的更新

update(BIT, x)
  while ( x < maxn )
    BIT[x] += val
    x += x & -x

2D BIT的更新如下:

update2DBIT(x, y)

// update BIT at index x (from bottom, in the image)
while ( x < maxn )
    update(BIT[x], y)
    x += x & -x
C++
// A C++ program implementing the above queries
#include
#define maxn 2005
using namespace std;
 
// 2D Binary Indexed Tree. Note: global variable
// will have initially all elements zero
int bit[maxn][maxn];
 
// function to add a point at (x, y)
void update(int x, int y)
{
    int y1;
    while (x < maxn)
    {
        // x is the xth BIT that will be updated
        // while y is the indices where an update
        // will be made in xth BIT
        y1 = y;
        while ( y1 < maxn )
        {
            bit[x][y1]++;
            y1 += ( y1 & -y1 );
        }
 
        // next BIT that should be updated
        x += x & -x;
    }
}
 
// Function to return number of points in the
// rectangle (1, 1), (x, y)
int query(int x, int y)
{
    int res = 0, y1;
    while (x > 0)
    {
        // xth BIT's yth node must be added to the result
        y1 = y;
        while (y1 > 0)
        {
            res += bit[x][y1];
            y1 -= y1 & -y1;
        }
 
        // next BIT that will contribute to the result
        x -= x & -x;
    }
    return res;
}
 
// (x1, y1) is the lower left and (x2, y2) is the
// upper right corner of the rectangle
int pointsInRectangle(int x1, int y1, int x2, int y2)
{
    // Returns number of points in the rectangle
    // (x1, y1), (x2, y2) as described in text above
    return query(x2, y2) - query(x1 - 1, y2) -W
           query(x2, y1 - 1) + query(x1 - 1, y1 - 1);
}
 
// Returns count of triangles with n points, i.e.,
// it returns nC3
int findTriangles(int n)
{
    // returns pts choose 3
    return (n * (n - 1) * (n - 2)) / 6;
}
 
//driver code
int main()
{
    //inserting points
    update(2, 2);
    update(3, 5);
    update(4, 2);
    update(4, 5);
    update(5, 4);
 
    cout << "No. of triangles in the rectangle (1, 1)"
            " (6, 6) are: "
         << findTriangles(pointsInRectangle(1, 1, 6, 6));
 
    update(3, 3);
 
    cout << "\nNo. of triangles in the rectangle (1, 1)"
            " (6, 6) are: "
         << findTriangles( pointsInRectangle(1, 1, 6, 6));
 
    return 0;
}


Java
// Java program implementing the above queries
import java.util.*;
class GFG
{
static int maxn = 2005;
 
// 2D Binary Indexed Tree. Note: global variable
// will have initially all elements zero
static int [][]bit = new int[maxn][maxn];
 
// function to add a point at (x, y)
static void update(int x, int y)
{
    int y1;
    while (x < maxn)
    {
        // x is the xth BIT that will be updated
        // while y is the indices where an update
        // will be made in xth BIT
        y1 = y;
        while ( y1 < maxn )
        {
            bit[x][y1]++;
            y1 += (y1 & -y1);
        }
 
        // next BIT that should be updated
        x += x & -x;
    }
}
 
// Function to return number of points in the
// rectangle (1, 1), (x, y)
static int query(int x, int y)
{
    int res = 0, y1;
    while (x > 0)
    {
        // xth BIT's yth node
        // must be added to the result
        y1 = y;
        while (y1 > 0)
        {
            res += bit[x][y1];
            y1 -= y1 & -y1;
        }
 
        // next BIT that will contribute to the result
        x -= x & -x;
    }
    return res;
}
 
// (x1, y1) is the lower left and (x2, y2) is the
// upper right corner of the rectangle
static int pointsInRectangle(int x1, int y1,
                             int x2, int y2)
{
    // Returns number of points in the rectangle
    // (x1, y1), (x2, y2) as described in text above
    return query(x2, y2) - query(x1 - 1, y2) -
           query(x2, y1 - 1) +
           query(x1 - 1, y1 - 1);
}
 
// Returns count of triangles with n points, i.e.,
// it returns nC3
static int findTriangles(int n)
{
    // returns pts choose 3
    return (n * (n - 1) * (n - 2)) / 6;
}
 
// Driver Code
public static void main(String[] args)
{
    // inserting points
    update(2, 2);
    update(3, 5);
    update(4, 2);
    update(4, 5);
    update(5, 4);
 
    System.out.print("No. of triangles in the " +
                     "rectangle (1, 1) (6, 6) are: " + 
                      findTriangles(pointsInRectangle(1, 1, 6, 6)));
 
    update(3, 3);
 
    System.out.print("\nNo. of triangles in the " +
                     "rectangle (1, 1) (6, 6) are: " +
                     findTriangles( pointsInRectangle(1, 1, 6, 6)));
}
}
 
// This code is contributed by Rajput-Ji


Python3
# A Python3 program implementing
# the above queries
maxn = 2005
 
# 2D Binary Indexed Tree.
# Note: global variable
# will have initially all
# elements zero
bit = [[0 for j in range(maxn)]
          for i in range(maxn)]
 
# function to add a point
# at(x, y)
def update(x, y):
 
    y1 = 0
    while (x < maxn):
     
        # x is the xth BIT that will
        # be updated while y is the
        # indices where an update
        # will be made in xth BIT
        y1 = y
         
        while (y1 < maxn):       
            bit[x][y1] += 1
            y1 += (y1 & -y1)
 
        # next BIT that should
        # be updated
        x += x & -x
 
# Function to return number of
# points in the rectangle(1, 1),
# (x, y)
def query(x, y):
 
    res = 0
    y1 = 0
     
    while (x > 0):
     
        # xth BIT's yth node must
        # be added to the result
        y1 = y
         
        while (y1 > 0):       
            res += bit[x][y1]
            y1 -= y1 & -y1       
 
        # next BIT that will contribute
        # to the result
        x -= x & -x
     
    return res
 
# (x1, y1) is the lower left
# and (x2, y2) is the upper
# right corner of the rectangle
def pointsInRectangle(x1, y1,
                      x2, y2):
 
    # Returns number of points
    # in the rectangle (x1, y1),
    # (x2, y2) as described in
    # text above
    return (query(x2, y2) - query(x1 - 1, y2) -
            query(x2, y1 - 1) + query(x1 - 1, y1 - 1))
 
# Returns count of triangles with
# n points, i.e., it returns nC3
def findTriangles(n):
 
    # returns pts choose 3
    return ((n * (n - 1) *
            (n - 2)) // 6)
 
# Driver code
if __name__ == "__main__":
 
    # inserting points
    update(2, 2)
    update(3, 5)
    update(4, 2)
    update(4, 5)
    update(5, 4)
 
    print("No. of triangles in the " +
          "rectangle (1, 1)  (6, 6) are: ",
           findTriangles(pointsInRectangle(1, 1,
                                           6, 6)))
    update(3, 3)
    print("No. of triangles in the rectangle " +
          "(1, 1) (6, 6) are:", findTriangles(
            pointsInRectangle(1, 1, 6, 6)))
 
# This code is contributed by Rutvik_56


C#
// C# program implementing the above queries
using System;
 
class GFG
{
static int maxn = 2005;
 
// 2D Binary Indexed Tree. Note: global variable
// will have initially all elements zero
static int [,]bit = new int[maxn, maxn];
 
// function to add a point at (x, y)
static void update(int x, int y)
{
    int y1;
    while (x < maxn)
    {
        // x is the xth BIT that will be updated
        // while y is the indices where an update
        // will be made in xth BIT
        y1 = y;
        while (y1 < maxn)
        {
            bit[x, y1]++;
            y1 += (y1 & -y1);
        }
 
        // next BIT that should be updated
        x += x & -x;
    }
}
 
// Function to return number of points in the
// rectangle (1, 1), (x, y)
static int query(int x, int y)
{
    int res = 0, y1;
    while (x > 0)
    {
        // xth BIT's yth node
        // must be added to the result
        y1 = y;
        while (y1 > 0)
        {
            res += bit[x, y1];
            y1 -= y1 & -y1;
        }
 
        // next BIT that will
        // contribute to the result
        x -= x & -x;
    }
    return res;
}
 
// (x1, y1) is the lower left and (x2, y2) is the
// upper right corner of the rectangle
static int pointsInRectangle(int x1, int y1,
                             int x2, int y2)
{
    // Returns number of points in the rectangle
    // (x1, y1), (x2, y2) as described in text above
    return query(x2, y2) - query(x1 - 1, y2) -
           query(x2, y1 - 1) +
            query(x1 - 1, y1 - 1);
}
 
// Returns count of triangles with n points, i.e.,
// it returns nC3
static int findTriangles(int n)
{
    // returns pts choose 3
    return (n * (n - 1) * (n - 2)) / 6;
}
 
// Driver Code
public static void Main(String[] args)
{
    // inserting points
    update(2, 2);
    update(3, 5);
    update(4, 2);
    update(4, 5);
    update(5, 4);
 
    Console.Write("No. of triangles in the " +
             "rectangle (1, 1) (6, 6) are: " +
              findTriangles(pointsInRectangle(1, 1, 6, 6)));
 
    update(3, 3);
 
    Console.Write("\nNo. of triangles in the " +
               "rectangle (1, 1) (6, 6) are: " +
                findTriangles( pointsInRectangle(1, 1, 6, 6)));
}
}
 
// This code is contributed by PrinciRaj1992


输出:

No of triangles in the rectangle (1, 1) (6, 6) are: 10
No of triangles in the rectangle (1, 1) (6, 6) are: 20