Counting Triangles in a Rectangular space using BIT
Last Updated :
14 Jun, 2023
Pre-requisite: BIT(Binary Indexed Tree or Fenwick Tree), 2D BIT
Given a 2D plane, respond to Q queries, each of the following type:
- Insert x y – Insert a point (x, y) coordinate.
- Triangle x1 y1 x2 y2 – Print the number of triangles that can be formed, by joining the points inside the rectangle, described by two points (x1, y1) and (x2, y2), (x1, y1) is the lower-left corner while (x2, y2) is the upper right corner. We will represent it as {(x1, y1), (x2, y2)}.(Include the triangles with zero areas also in your answer)
Example:

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.
Let’s say we somehow have a mechanism to find the number of points inside a given rectangle, let the number of points be ‘m’ in an instance.
The number of triangles that can be formed with it are mC3 (every 3 points when joined will make a triangle); if we had to count only degenerate triangles, we would have to subtract the number of triangles with zero areas or formed from points on the same line.
Now we sneak into the mechanism to find the number of points in a rectangle; let’s assume we have a mechanism to find the number of points inside a rectangle.
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)}
Now once we find a way to find P(x, y), we are done.
If all the insert queries were made first, then all the triangle queries, it would have been an easy job, we could maintain a 2D table to store the points and table[x][y] would contain the total number of points in the rectangle {(1, 1), (x, y)}.
It can be created using the following DP:
table[x][y] = table[x][y – 1] + table[x – 1][y] – table[x – 1][y – 1]
Or we can use a 2D BIT to insert a point and evaluate P(x, y). For visualization of a 2D BIT, refer Top Coder. The image shows a 16 * 8 2D BIT, and the state after an insertion at (5, 3), the blue nodes are the onces that are updated.
The horizontal BITs correspond to 3, and store 1 at index 3, 1 at index 4, and 1 at index 8; while the vertical representation corresponds to which horizontal BITs will receive that update, the ones that correspond to 5, so 5th BIT from the bottom gets an update, 6th BIT, then 8th BIT, and then 16th BIT.
Let’s consider update in a 1D BIT
update(BIT, x)
while ( x < maxn )
BIT[x] += val
x += x & -x
Update for 2D BIT goes like:
update2DBIT(x, y)
// update BIT at index x (from bottom, in the image)
while ( x < maxn )
update(BIT[x], y)
x += x & -x
C++
#include<bits/stdc++.h>
#define maxn 2005
using namespace std;
int bit[maxn][maxn];
void update( int x, int y)
{
int y1;
while (x < maxn)
{
y1 = y;
while ( y1 < maxn )
{
bit[x][y1]++;
y1 += ( y1 & -y1 );
}
x += x & -x;
}
}
int query( int x, int y)
{
int res = 0, y1;
while (x > 0)
{
y1 = y;
while (y1 > 0)
{
res += bit[x][y1];
y1 -= y1 & -y1;
}
x -= x & -x;
}
return res;
}
int pointsInRectangle( int x1, int y1, int x2, int y2)
{
return query(x2, y2) - query(x1 - 1, y2) -
query(x2, y1 - 1) + query(x1 - 1, y1 - 1);
}
int findTriangles( int n)
{
return (n * (n - 1) * (n - 2)) / 6;
}
int main()
{
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
import java.util.*;
class GFG
{
static int maxn = 2005 ;
static int [][]bit = new int [maxn][maxn];
static void update( int x, int y)
{
int y1;
while (x < maxn)
{
y1 = y;
while ( y1 < maxn )
{
bit[x][y1]++;
y1 += (y1 & -y1);
}
x += x & -x;
}
}
static int query( int x, int y)
{
int res = 0 , y1;
while (x > 0 )
{
y1 = y;
while (y1 > 0 )
{
res += bit[x][y1];
y1 -= y1 & -y1;
}
x -= x & -x;
}
return res;
}
static int pointsInRectangle( int x1, int y1,
int x2, int y2)
{
return query(x2, y2) - query(x1 - 1 , y2) -
query(x2, y1 - 1 ) +
query(x1 - 1 , y1 - 1 );
}
static int findTriangles( int n)
{
return (n * (n - 1 ) * (n - 2 )) / 6 ;
}
public static void main(String[] args)
{
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 )));
}
}
|
Python3
maxn = 2005
bit = [[ 0 for j in range (maxn)]
for i in range (maxn)]
def update(x, y):
y1 = 0
while (x < maxn):
y1 = y
while (y1 < maxn):
bit[x][y1] + = 1
y1 + = (y1 & - y1)
x + = x & - x
def query(x, y):
res = 0
y1 = 0
while (x > 0 ):
y1 = y
while (y1 > 0 ):
res + = bit[x][y1]
y1 - = y1 & - y1
x - = x & - x
return res
def pointsInRectangle(x1, y1,
x2, y2):
return (query(x2, y2) - query(x1 - 1 , y2) -
query(x2, y1 - 1 ) + query(x1 - 1 , y1 - 1 ))
def findTriangles(n):
return ((n * (n - 1 ) *
(n - 2 )) / / 6 )
if __name__ = = "__main__" :
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 )))
|
C#
using System;
class GFG
{
static int maxn = 2005;
static int [,]bit = new int [maxn, maxn];
static void update( int x, int y)
{
int y1;
while (x < maxn)
{
y1 = y;
while (y1 < maxn)
{
bit[x, y1]++;
y1 += (y1 & -y1);
}
x += x & -x;
}
}
static int query( int x, int y)
{
int res = 0, y1;
while (x > 0)
{
y1 = y;
while (y1 > 0)
{
res += bit[x, y1];
y1 -= y1 & -y1;
}
x -= x & -x;
}
return res;
}
static int pointsInRectangle( int x1, int y1,
int x2, int y2)
{
return query(x2, y2) - query(x1 - 1, y2) -
query(x2, y1 - 1) +
query(x1 - 1, y1 - 1);
}
static int findTriangles( int n)
{
return (n * (n - 1) * (n - 2)) / 6;
}
public static void Main(String[] args)
{
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)));
}
}
|
Javascript
<script>
var maxn = 2005;
var bit = Array(maxn).fill().map(()=>Array(maxn).fill(0));
function update(x , y) {
var y1;
while (x < maxn) {
y1 = y;
while (y1 < maxn) {
bit[x][y1]++;
y1 += (y1 & -y1);
}
x += x & -x;
}
}
function query(x , y) {
var res = 0, y1;
while (x > 0) {
y1 = y;
while (y1 > 0) {
res += bit[x][y1];
y1 -= y1 & -y1;
}
x -= x & -x;
}
return res;
}
function pointsInRectangle(x1 , y1 , x2 , y2) {
return query(x2, y2) - query(x1 - 1, y2) -
query(x2, y1 - 1) + query(x1 - 1, y1 - 1);
}
function findTriangles(n) {
return (n * (n - 1) * (n - 2)) / 6;
}
update(2, 2);
update(3, 5);
update(4, 2);
update(4, 5);
update(5, 4);
document.write( "No. of triangles in the " +
"rectangle (1, 1) (6, 6) are: "
+ findTriangles(pointsInRectangle(1, 1, 6, 6)));
update(3, 3);
document.write( "<br/>No. of triangles in the " +
"rectangle (1, 1) (6, 6) are: "
+ findTriangles(pointsInRectangle(1, 1, 6, 6)));
</script>
|
Output:
No of triangles in the rectangle (1, 1) (6, 6) are: 10
No of triangles in the rectangle (1, 1) (6, 6) are: 20
Time Complexity: For each query of either type: O(log(x) * log(y)) Or infact: O( number of ones in binary representation of x * number of ones in a binary representation of y )
Total time complexity: O(Q * log(maxX) * log(maxY))
Similar Reads
Count set bits in an integer using Lookup Table
Write an efficient program to count number of 1s in binary representation of an integer.Examples: Input : n = 6Output : 2Binary representation of 6 is 110 and has 2 set bits Input : n = 13Output : 3Binary representation of 13 is 1101 and has 3 set bits In the previous post we had seen different meth
6 min read
Count number of set bits in a range using bitset
Given a large binary number.The task is to count the number of 1's in a given range from L to R (1 based indexing).Examples: Input : s = "101101011010100000111", L = 6, R = 15 Output : 5 s [L : R] = "1011010100" There is only 5 set bits.Input : s = "10110", L = 2, R = 5 Output : 2 Approach: Convert
5 min read
Count set bits in a range
Given a non-negative number n and two values l and r. The problem is to count the number of set bits in the range l to r in the binary representation of n, i.e, to count set bits from the rightmost lth bit to the rightmost rth bit. Constraint: 1 <= l <= r <= number of bits in the binary rep
6 min read
Python | Count unset bits in a range
Given a non-negative number n and two values l and r. The problem is to count the number of unset bits in the range l to r in the binary representation of n, i.e, to count unset bits from the rightmost lth bit to the rightmost rth bit. Examples: Input : n = 42, l = 2, r = 5 Output : 2 (42)10 = (1010
2 min read
Python | Count set bits in a range
Given a non-negative number n and two values l and r. The problem is to count the number of set bits in the range l to r in the binary representation of n, i.e, to count set bits from the rightmost lth bit to the rightmost rth bit. Constraint: 1 <= l <= r <= number of bits in the binary rep
2 min read
Count unset bits in a range
Given a non-negative number n and two values l and r. The problem is to count the number of unset bits in the range l to r in the binary representation of n, i.e, to count unset bits from the rightmost lth bit to the rightmost rth bit.Examples: Input : n = 42, l = 2, r = 5 Output : 2 (42)10 = (10101
6 min read
Count of numbers having only one unset bit in a range [L,R]
Given two integers L and R, the task is to count the numbers having only one unset bit in the range [L, R]. Examples: Input: L = 4, R = 9Output: 2Explanation:The binary representation of all numbers in the range [4, 9] are 4 = (100)2 5 = (101)2 6 = (110)2 7 = (111)2 8 = (1000)2 9 = (1001)2 Out of al
11 min read
Count Set-bits of number using Recursion
Given a number N. The task is to find the number of set bits in its binary representation using recursion. Examples: Input : 21 Output : 3 21 represented as 10101 in binary representation Input : 16 Output : 1 16 represented as 10000 in binary representation Approach: First, check the LSB of the num
4 min read
Count set bits in an integer
Write an efficient program to count the number of 1s in the binary representation of an integer.Examples : Input : n = 6Output : 2Binary representation of 6 is 110 and has 2 set bits Input : n = 13Output : 3Binary representation of 13 is 1101 and has 3 set bits [Naive Approach] - One by One Counting
15+ min read
Count trailing zero bits using lookup table
Given an integer, count the number of trailing zeroes. For example, for n = 12, its binary representation is 1100 and number of trailing zero bits is 2. Examples : Input : 8 Output : 3 Binary of 8 is 1000, so there are three trailing zero bits. Input : 18 Output : 1 Binary of 18 is 10010, so there i
7 min read