Skip to content
geeksforgeeks
  • Tutorials
    • Python
    • Java
    • Data Structures & Algorithms
    • ML & Data Science
    • Interview Corner
    • Programming Languages
    • Web Development
    • CS Subjects
    • DevOps And Linux
    • School Learning
    • Practice Coding Problems
  • Courses
    • DSA to Development
    • Get IBM Certification
    • Newly Launched!
      • Master Django Framework
      • Become AWS Certified
    • For Working Professionals
      • Interview 101: DSA & System Design
      • Data Science Training Program
      • JAVA Backend Development (Live)
      • DevOps Engineering (LIVE)
      • Data Structures & Algorithms in Python
    • For Students
      • Placement Preparation Course
      • Data Science (Live)
      • Data Structure & Algorithm-Self Paced (C++/JAVA)
      • Master Competitive Programming (Live)
      • Full Stack Development with React & Node JS (Live)
    • Full Stack Development
    • Data Science Program
    • All Courses
  • DSA Tutorial
  • Data Structures
  • Algorithms
  • Array
  • Strings
  • Linked List
  • Stack
  • Queue
  • Tree
  • Graph
  • Searching
  • Sorting
  • Recursion
  • Dynamic Programming
  • Binary Tree
  • Binary Search Tree
  • Heap
  • Hashing
  • Divide & Conquer
  • Mathematical
  • Geometric
  • Bitwise
  • Greedy
  • Backtracking
  • Branch and Bound
  • Matrix
  • Pattern Searching
  • Randomized
Open In App
Next Article:
Counting Triangles in a Rectangular space using BIT
Next article icon

Counting Triangles in a Rectangular space using BIT

Last Updated : 14 Jun, 2023
Comments
Improve
Suggest changes
Like Article
Like
Report

Pre-requisite: BIT(Binary Indexed Tree or Fenwick Tree), 2D BIT
Given a 2D plane, respond to Q queries, each of the following type: 

  1. Insert x y - Insert a point (x, y) coordinate.
  2. 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++
// A C++ program implementing the above queries #include<bits/stdc++.h> #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) -            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 
JavaScript
<script>  // JavaScript program implementing the above queries     var maxn = 2005;      // 2D Binary Indexed Tree. Note: global variable     // will have initially all elements zero      var bit = Array(maxn).fill().map(()=>Array(maxn).fill(0));      // function to add a point at (x, y)     function update(x , y) {         var 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)     function query(x , y) {         var 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     function 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     function findTriangles(n) {         // returns pts choose 3         return (n * (n - 1) * (n - 2)) / 6;     }      // Driver Code              // inserting points         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)));  // This code contributed by gauravrajput1  </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)) 


Next Article
Counting Triangles in a Rectangular space using BIT

S

Saumye Malhotra
Improve
Article Tags :
  • Advanced Data Structure
  • DSA
  • triangle
  • Binary Indexed Tree
Practice Tags :
  • Advanced Data Structure

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 bitsInput : n = 13Output : 3Binary representation of 13 is 1101 and has 3 set bits In the previous post we had seen different metho
    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
    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
geeksforgeeks-footer-logo
Corporate & Communications Address:
A-143, 7th Floor, Sovereign Corporate Tower, Sector- 136, Noida, Uttar Pradesh (201305)
Registered Address:
K 061, Tower K, Gulshan Vivante Apartment, Sector 137, Noida, Gautam Buddh Nagar, Uttar Pradesh, 201305
GFG App on Play Store GFG App on App Store
Advertise with us
  • Company
  • About Us
  • Legal
  • Privacy Policy
  • In Media
  • Contact Us
  • Advertise with us
  • GFG Corporate Solution
  • Placement Training Program
  • Languages
  • Python
  • Java
  • C++
  • PHP
  • GoLang
  • SQL
  • R Language
  • Android Tutorial
  • Tutorials Archive
  • DSA
  • Data Structures
  • Algorithms
  • DSA for Beginners
  • Basic DSA Problems
  • DSA Roadmap
  • Top 100 DSA Interview Problems
  • DSA Roadmap by Sandeep Jain
  • All Cheat Sheets
  • Data Science & ML
  • Data Science With Python
  • Data Science For Beginner
  • Machine Learning
  • ML Maths
  • Data Visualisation
  • Pandas
  • NumPy
  • NLP
  • Deep Learning
  • Web Technologies
  • HTML
  • CSS
  • JavaScript
  • TypeScript
  • ReactJS
  • NextJS
  • Bootstrap
  • Web Design
  • Python Tutorial
  • Python Programming Examples
  • Python Projects
  • Python Tkinter
  • Python Web Scraping
  • OpenCV Tutorial
  • Python Interview Question
  • Django
  • Computer Science
  • Operating Systems
  • Computer Network
  • Database Management System
  • Software Engineering
  • Digital Logic Design
  • Engineering Maths
  • Software Development
  • Software Testing
  • DevOps
  • Git
  • Linux
  • AWS
  • Docker
  • Kubernetes
  • Azure
  • GCP
  • DevOps Roadmap
  • System Design
  • High Level Design
  • Low Level Design
  • UML Diagrams
  • Interview Guide
  • Design Patterns
  • OOAD
  • System Design Bootcamp
  • Interview Questions
  • Inteview Preparation
  • Competitive Programming
  • Top DS or Algo for CP
  • Company-Wise Recruitment Process
  • Company-Wise Preparation
  • Aptitude Preparation
  • Puzzles
  • School Subjects
  • Mathematics
  • Physics
  • Chemistry
  • Biology
  • Social Science
  • English Grammar
  • Commerce
  • World GK
  • GeeksforGeeks Videos
  • DSA
  • Python
  • Java
  • C++
  • Web Development
  • Data Science
  • CS Subjects
@GeeksforGeeks, Sanchhaya Education Private Limited, All rights reserved
We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood our Cookie Policy & Privacy Policy
Lightbox
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
geeksforgeeks-suggest-icon
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.
geeksforgeeks-improvement-icon
Suggest Changes
min 4 words, max Words Limit:1000

Thank You!

Your suggestions are valuable to us.

What kind of Experience do you want to share?

Interview Experiences
Admission Experiences
Career Journeys
Work Experiences
Campus Experiences
Competitive Exam Experiences