Skip to content
geeksforgeeks
  • 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
  • Tutorials
    • Data Structures & Algorithms
    • ML & Data Science
    • Interview Corner
    • Programming Languages
    • Web Development
    • CS Subjects
    • DevOps And Linux
    • School Learning
  • Practice
    • Build your AI Agent
    • GfG 160
    • Problem of the Day
    • Practice Coding Problems
    • GfG SDE Sheet
  • Contests
    • Accenture Hackathon (Ending Soon!)
    • GfG Weekly [Rated Contest]
    • Job-A-Thon Hiring Challenge
    • All Contests and Events
  • DSA
  • Practice Bitwise Algorithms
  • MCQs on Bitwise Algorithms
  • Tutorial on Biwise Algorithms
  • Binary Representation
  • Bitwise Operators
  • Bit Swapping
  • Bit Manipulation
  • Count Set bits
  • Setting a Bit
  • Clear a Bit
  • Toggling a Bit
  • Left & Right Shift
  • Gray Code
  • Checking Power of 2
  • Important Tactics
  • Bit Manipulation for CP
  • Fast Exponentiation
Open In App
Next Article:
Sum of bitwise OR of all subarrays
Next article icon

Queries for Sum of Bitwise AND of all Subarrays in a Range

Last Updated : 11 Mar, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Given an array arr[] of size N, the task is to answer a set of Q queries, each in the format of queries[i][0] and queries[i][1]. For each queries[i], find the sum of Bitwise AND of all subarrays whose elements lie in the range [queries[i][0], queries[i][1]].

Examples:

Input: N = 3, arr[] = {1, 0, 2}, Q = 2, queries[][] = {{1, 2}, {2, 3}}
Output: 1 2
Explanation:

  • For the first query AND[1] + AND[0] + AND[1, 0] = 1.
  • For the second query AND[0] + AND[2] + AND[0, 2] = 2.

Input: N = 4, arr[] = {4, 3, 2, 1}, Q = 3, queries[][] = {{1, 3}, {2, 4}, {1, 4}}
Output: 11 8 12
Explanation:

  • For the first query AND[4] + AND[3] + AND[2] + AND[4, 3] + AND[4, 3, 2] + AND[3, 2] = 11.
  • For the second query AND[3] + AND[2] + AND[1] + AND[3, 2] + AND[3, 2, 1] + AND[2, 1] = 8.
  • For the third query AND[4] + AND[3] + AND[2] + AND[1] + AND[4, 3] + AND[4, 3, 2] + AND[4, 3, 2, 1] + AND[3, 2] + AND[3, 2, 1] + AND[2, 1] = 12.

Approach: This can be solved with the following idea:

The main idea is to use precomputation to optimize the Bitwise AND calculation for subarrays. This is achieved by maintaining arrays that store the count and cumulative sum of consecutive set bits in the binary representation of the array elements. The final result is computed by considering the contributions of each bit position separately.

Step-by-step algorithm:

  • Create two 2D arrays, pref[20][N] and next[20][N] where N is the length of array arr[].
  • pref[j][i] will store the count and cumulative sum of set bits in the binary representation of arr[i] at bit position j.
  • next[j][i] will store the next index with a set bit to the right of index i.
  • Iterate Through Bits and Array Elements, for each bit position j from 0 to 19:
    • Calculate the count of set bits at bit position j in arr[i].
    • Update pref[j][i] with the count and cumulative sum of set bits.
    • Update next[j][i] with the next index having a set bit to the right of index i.
  • Iterate through each bit position j (from 0 to 19) and calculate the values for pref[][] and next[][] based on the binary representation of array elements.
  • Initialize an empty vector ans to store the results.
  • For each query [u, v], iterate through each bit position j and compute the contribution of the set bits at position j within the subarray [u, v]. Update the result by adding the contribution multiplied by 2^j.
  • Append the final result to the ans vector.
  • Return the ans vector containing the results for all queries.

Below is the implementation of the algorithm:

C++
#include <bits/stdc++.h> using namespace std;  // Function to find sum of AND vector<long long> summationOfAnd(int N, vector<int>& arr,                                 int Q,                                 vector<vector<int> >& queries) {      // Declare a 2D vector     vector<vector<pair<int, int> > > pref(         20, vector<pair<int, int> >(N));     vector<vector<int> > next(20, vector<int>(N, 0));      // Start Iterating     for (int j = 0; j < 20; j++) {          int curr = 0, sum = 0;          // Iterate in array         for (int i = 0; i < N; i++) {              // Get the AND value             if ((arr[i] & (1 << j)) > 0) {                 curr++;                 sum += curr;                 pref[j][i] = { curr, sum };             }             else {                  // If curr value is greater than 0                 if (curr > 0) {                     next[j][i - 1] = i - 1;                 }                  // Set the value to 0                 // for next iteration                 curr = 0;                 pref[j][i] = { curr, sum };             }         }          // Update the value in next vector         next[j][N - 1] = N - 1;          // Start Iterating from n -2         for (int i = N - 2; i >= 0; i--) {             if (next[j][i] == 0) {                 next[j][i] = next[j][i + 1];             }         }     }     vector<long long> ans;     // Iterate in B     for (int i = 0; i < Q; i++) {          int u = queries[i][0] - 1;         int v = queries[i][1] - 1;         long long res = 0;          // Iterate again for 20 times         for (int j = 0; j < 20; j++) {             long long temp;              // Get the temp value             if (u == 0) {                 temp = pref[j][v].second;             }             else if (pref[j][u].first == 0) {                 temp = pref[j][v].second - pref[j][u].second;             }             else {                 // Minumum value for right                 int right = min(v, next[j][u]);                  temp = pref[j][v].second                     - pref[j][right].second;                 if (pref[j][right].first > 0) {                     temp += (right - u + 1)                             * (right - u + 2) / 2;                 }             }             // Add the value to res             res += (temp * (1 << j));         }          // Store it in ans         ans.push_back(res);     }      // Return vector ans     return ans; }  // Driver code int main() {      int N = 4;     vector<int> arr = { 4, 3, 2, 1 };     int Q = 3;     vector<vector<int> > queries         = { { 1, 3 }, { 2, 4 }, { 1, 4 } };      // Function call     vector<long long> ans = summationOfAnd(N, arr, Q, queries);      for (auto a : ans) {         cout << a << " ";     }     return 0; } 
Java
import java.util.*;  public class Main {      // Function to find sum of AND     static List<Long> summationOfAnd(int N, List<Integer> arr, int Q, List<List<Integer>> queries) {          // Declare a 2D vector         List<List<Pair>> pref = new ArrayList<>(20);         List<List<Integer>> next = new ArrayList<>(20);         for (int i = 0; i < 20; i++) {             pref.add(new ArrayList<>(Collections.nCopies(N, new Pair(0, 0))));             next.add(new ArrayList<>(Collections.nCopies(N, 0)));         }          // Start iterating         for (int j = 0; j < 20; j++) {             int curr = 0, sum = 0;              // Iterate in array             for (int i = 0; i < N; i++) {                 // Get the AND value                 if ((arr.get(i) & (1 << j)) > 0) {                     curr++;                     sum += curr;                     pref.get(j).set(i, new Pair(curr, sum));                 } else {                     // If curr value is greater than 0                     if (curr > 0) {                         next.get(j).set(i - 1, i - 1);                     }                     // Set the value to 0 for next iteration                     curr = 0;                     pref.get(j).set(i, new Pair(curr, sum));                 }             }             // Update the value in next list             next.get(j).set(N - 1, N - 1);              // Start Iterating from n -2             for (int i = N - 2; i >= 0; i--) {                 if (next.get(j).get(i) == 0) {                     next.get(j).set(i, next.get(j).get(i + 1));                 }             }         }         List<Long> ans = new ArrayList<>();         // Iterate in B         for (List<Integer> query : queries) {             int u = query.get(0) - 1;             int v = query.get(1) - 1;             long res = 0;             // Iterate again for 20 times             for (int j = 0; j < 20; j++) {                 long temp;                 // Get the temp value                 if (u == 0) {                     temp = pref.get(j).get(v).second;                 } else if (pref.get(j).get(u).first == 0) {                     temp = pref.get(j).get(v).second - pref.get(j).get(u).second;                 } else {                     // Minimum value for right                     int right = Math.min(v, next.get(j).get(u));                     temp = pref.get(j).get(v).second - pref.get(j).get(right).second;                     if (pref.get(j).get(right).first > 0) {                         temp += (right - u + 1) * (right - u + 2) / 2;                     }                 }                 // Add the value to res                 res += (temp * (1L << j));             }             // Store it in ans             ans.add(res);         }         // Return list ans         return ans;     }      // Pair class to store pair values     static class Pair {         int first;         int second;          Pair(int first, int second) {             this.first = first;             this.second = second;         }     }      // Driver code     public static void main(String[] args) {          int N = 4;         List<Integer> arr = Arrays.asList(4, 3, 2, 1);         int Q = 3;         List<List<Integer>> queries = Arrays.asList(Arrays.asList(1, 3), Arrays.asList(2, 4), Arrays.asList(1, 4));          // Function call         List<Long> ans = summationOfAnd(N, arr, Q, queries);          // Print the result         for (long a : ans) {             System.out.print(a + " ");         }     } } 
C#
using System; using System.Collections.Generic;  class Solution {     // Function to find sum of AND     static List<long> SummationOfAnd(int N, List<int> arr, int Q, List<List<int>> queries) {         // Declare a 2D list         List<List<Tuple<int, int>>> pref = new List<List<Tuple<int, int>>>();         List<List<int>> next = new List<List<int>>();          // Initialize pref and next lists         for (int i = 0; i < 20; i++) {             pref.Add(new List<Tuple<int, int>>());             next.Add(new List<int>());             for (int j = 0; j < N; j++) {                 pref[i].Add(new Tuple<int, int>(0, 0));                 next[i].Add(0);             }         }          // Start Iterating         for (int j = 0; j < 20; j++) {             int curr = 0, sum = 0;              // Iterate in array             for (int i = 0; i < N; i++) {                 // Get the AND value                 if ((arr[i] & (1 << j)) > 0) {                     curr++;                     sum += curr;                     pref[j][i] = new Tuple<int, int>(curr, sum);                 }                 else {                     // If curr value is greater than 0                     if (curr > 0) {                         next[j][i - 1] = i - 1;                     }                      // Set the value to 0 for next iteration                     curr = 0;                     pref[j][i] = new Tuple<int, int>(curr, sum);                 }             }              // Update the value in next vector             next[j][N - 1] = N - 1;              // Start Iterating from n -2             for (int i = N - 2; i >= 0; i--) {                 if (next[j][i] == 0) {                     next[j][i] = next[j][i + 1];                 }             }         }          List<long> ans = new List<long>();          // Iterate in B         for (int i = 0; i < Q; i++) {             int u = queries[i][0] - 1;             int v = queries[i][1] - 1;             long res = 0;              // Iterate again for 20 times             for (int j = 0; j < 20; j++) {                 long temp;                  // Get the temp value                 if (u == 0) {                     temp = pref[j][v].Item2;                 }                 else if (pref[j][u].Item1 == 0) {                     temp = pref[j][v].Item2 - pref[j][u].Item2;                 }                 else {                     // Minimum value for right                     int right = Math.Min(v, next[j][u]);                     temp = pref[j][v].Item2 - pref[j][right].Item2;                     if (pref[j][right].Item1 > 0) {                         temp += (right - u + 1) * (right - u + 2) / 2;                     }                 }                 // Add the value to res                 res += (temp * (1 << j));             }              // Store it in ans             ans.Add(res);         }          // Return vector ans         return ans;     }      // Driver code     static void Main(string[] args) {         int N = 4;         List<int> arr = new List<int> { 4, 3, 2, 1 };         int Q = 3;         List<List<int>> queries = new List<List<int>> {             new List<int> { 1, 3 },             new List<int> { 2, 4 },             new List<int> { 1, 4 }         };          // Function call         List<long> ans = SummationOfAnd(N, arr, Q, queries);          foreach (long a in ans) {             Console.Write(a + " ");         }     } } 
Javascript
function GFG(N, arr, Q, queries) {     // Declare variables     let pref = new Array(20).fill(null).map(() => new Array(N).fill(null));     let next = new Array(20).fill(null).map(() => new Array(N).fill(0));     // Start Iterating     for (let j = 0; j < 20; j++) {         let curr = 0, sum = 0;         // Iterate over array         for (let i = 0; i < N; i++) {             // Get the AND value             if ((arr[i] & (1 << j)) > 0) {                 curr++;                 sum += curr;                 pref[j][i] = [curr, sum];             } else {                 // If curr value is greater than 0                 if (curr > 0) {                     next[j][i - 1] = i - 1;                 }                 curr = 0;                 pref[j][i] = [curr, sum];             }         }         // Update the value in next vector         next[j][N - 1] = N - 1;         // Start Iterating from n -2         for (let i = N - 2; i >= 0; i--) {             if (next[j][i] == 0) {                 next[j][i] = next[j][i + 1];             }         }     }          let ans = [];     // Iterate over queries     for (let i = 0; i < Q; i++) {         let u = queries[i][0] - 1;         let v = queries[i][1] - 1;         let res = 0;         // Iterate again for 20 times         for (let j = 0; j < 20; j++) {             let temp;             // Get the temp value             if (u === 0) {                 temp = pref[j][v][1];             } else if (pref[j][u][0] === 0) {                 temp = pref[j][v][1] - pref[j][u][1];             } else {                 // Minumum value for right                 let right = Math.min(v, next[j][u]);                 temp = pref[j][v][1] - pref[j][right][1];                 if (pref[j][right][0] > 0) {                     temp += (right - u + 1) * (right - u + 2) / 2;                 }             }             // Add the value to res             res += (temp * (1 << j));         }         // Store it in ans         ans.push(res);     }     // Return vector ans     return ans; } // Driver code function main() {     let N = 4;     let arr = [4, 3, 2, 1];     let Q = 3;     let queries = [[1, 3], [2, 4], [1, 4]];     // Function call     let ans = GFG(N, arr, Q, queries);     // Print the result     let output = "";     for (let a of ans) {         output += a + " ";     }     console.log(output.trim());  // Trim to remove trailing space } // Invoke main function main(); 
Python3
def solve(N, arr, Q, queries):     pref = [[[0, 0] for _ in range(N)] for _ in range(20)]     next = [[0 for _ in range(N)] for _ in range(20)]      for j in range(20):         curr, sum = 0, 0         for i in range(N):             if arr[i] & (1 << j):                 curr += 1                 sum += curr                 pref[j][i] = [curr, sum]             else:                 if curr > 0:                     next[j][i - 1] = i - 1                 curr = 0                 pref[j][i] = [curr, sum]         next[j][N - 1] = N - 1         for i in range(N - 2, -1, -1):             if next[j][i] == 0:                 next[j][i] = next[j][i + 1]      ans = []     for u, v in queries:         u -= 1         v -= 1         res = 0         for j in range(20):             if u == 0:                 temp = pref[j][v][1]             elif pref[j][u - 1][0] == 0:                 temp = pref[j][v][1] - pref[j][u - 1][1]             else:                 right = min(v, next[j][u - 1])                 temp = pref[j][v][1] - pref[j][right][1]                 if pref[j][right][0] > 0:                     temp += (right - u + 1) * (right - u + 2) // 2             res += temp * (1 << j)         ans.append(res)     return ans  # Driver code if __name__ == "__main__":     N = 4     arr = [4, 3, 2, 1]     Q = 3     queries = [(1, 3), (2, 4), (1, 4)]     ans = solve(N, arr, Q, queries)     for a in ans:         print(a, end=" ") 

Output
11 8 12 

Time Complexity: O(N + Q), where N is the size of input array arr[] and Q is the number of queries.
Auxiliary Space: O(N)


Next Article
Sum of bitwise OR of all subarrays

S

suru21
Improve
Article Tags :
  • Bit Magic
  • Geeks Premier League
  • DSA
  • Geeks Premier League 2023
  • Precomputation
Practice Tags :
  • Bit Magic

Similar Reads

  • Sum of bitwise AND of all subarrays
    Given an array consisting of N positive integers, find the sum of bit-wise and of all possible sub-arrays of the array. Examples: Input : arr[] = {1, 5, 8} Output : 15 Bit-wise AND of {1} = 1 Bit-wise AND of {1, 5} = 1 Bit-wise AND of {1, 5, 8} = 0 Bit-wise AND of {5} = 5 Bit-wise AND of {5, 8} = 0
    8 min read
  • Sum of bitwise OR of all subarrays
    Given an array of positive integers, find the total sum after performing the bit wise OR operation on all the sub arrays of a given array. Examples: Input : 1 2 3 4 5 Output : 71 Input : 6 5 4 3 2 Output : 84 First initialize the two variable sum=0, sum1=0, variable sum will store the total sum and,
    5 min read
  • Segment Tree for Range Bitwise OR and Range Minimum Queries
    There is an array of n elements, initially filled with zeros. The task is to perform q queries from given queries[][] and there are two types of queries, type 1 queries in the format {1, l, r, v} and type 2 queries in the format {2, l, r}. Type 1: Apply the operation ai = ai | v (bitwise OR) to all
    15+ min read
  • Sum of bitwise AND of all submatrices
    Given an NxN matrix, the task is to find the sum of bit-wise AND of all of its rectangular sub-matrices. Examples: Input : arr[][] = {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}} Output : 36 Explanation: All the possible submatrices will have AND value 1. Since, there are 36 submatrices in total, ans = 36 Input
    13 min read
  • Sum of bitwise AND of all possible subsets of given set
    Given an array, we need to calculate the Sum of Bit-wise AND of all possible subsets of the given array. Examples: Input : 1 2 3 Output : 9 For [1, 2, 3], all possible subsets are {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3} Bitwise AND of these subsets are, 1 + 2 + 3 + 0 + 1 + 2 + 0 = 9. So, th
    7 min read
  • Sum of Bitwise OR of all pairs in a given array
    Given an array "arr[0..n-1]" of integers. The task is to calculate the sum of Bitwise OR of all pairs, i.e. calculate the sum of "arr[i] | arr[j]" for all the pairs in the given array where i < j. Here '|' is a bitwise OR operator. The expected time complexity is O(n). Examples: Input: arr[] = {5
    13 min read
  • Subset Sum Queries in a Range using Bitset
    Given an array[] of N positive integers and M queries. Each query consists of two integers L and R represented by a range. For each query, find the count of numbers that lie in the given range which can be expressed as the sum of any subset of given array. Prerequisite : Subset Sum Queries using Bit
    7 min read
  • Sum of Bitwise And of all pairs in a given array
    Given an array "arr[0..n-1]" of integers, calculate sum of "arr[i] & arr[j]" for all the pairs in the given where i < j. Here & is bitwise AND operator. Expected time complexity is O(n). Examples : Input: arr[] = {5, 10, 15} Output: 15 Required Value = (5 & 10) + (5 & 15) + (10
    13 min read
  • Bitwise Operations in Subarrays: Query and Result
    Given a positive integer array A[] of size N and Q queries. Given a 2D integer array Queries[][] of length Q where each query has four integers l1, r1, l2, r2, the task is to calculate (Al1 & Al1+1 & Al1+2 ...& Ar1) | (Al2 & Al2+1 & Al2+2....& Ar2) and return an integer array
    9 min read
  • Print all subarrays with sum in a given range
    Given an array arr[] of positive integers and two integers L and R defining the range [L, R]. The task is to print the subarrays having sum in the range L to R. Examples: Input: arr[] = {1, 4, 6}, L = 3, R = 8Output: {1, 4}, {4}, {6}.Explanation: All the possible subarrays are the following{1] with
    5 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