Open In App

Min Queries

Last Updated : 11 Dec, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given an integer array A[] and q queries. Each query contains an integer x. 

For each query, Find the minimum index i such that A[i] ≥ x, and then decrease the value at position i by x, i.e., A[i] = A[i] - x. If there doesn't exist any index i satisfying the condition, then return 0.

Example:

Input: A[] = [3, 2, 4, 1, 5, 5, 2, 6], queries[] = [4, 4, 7, 1, 1]
Output: [3, 5, 0, 1, 1]
Explanation: Query 4: First A[i] ≥ 4 is at index 3. Output 3 and update A[3] = 0.
Query 4: Now A = [3, 2, 0, 1, 5, 5, 2, 6]. First A[i] ≥ 4 is index 5. Output 5 and update A[5] = 1.
Query 7: No value ≥ 7, so output 0.
Query 1: First A[i] ≥ 1 is index 1. Output 1 and update A[1] = 2.
Query 1: First A[i] ≥ 1 is again index 1. Output 1 and update A[1] = 1. 

[Naive Approach] Brute Force - O(n × q) Time and O(1) Space

The idea is to scan the array from left to right for every query. For each value x, it searches for the first index whose value is at least x, prints that index, and reduces the value at that position. This process repeats independently for each query, regardless of previous searches or updates. The method is simple and requires almost no extra space, but it becomes slow when the array size or number of queries is large because each query may require scanning the entire array.

C++
#include <iostream>
#include <vector>
using namespace std;

vector<int> processQueries(vector<int>& A, vector<int>& queries) {
    // array size
    int n = A.size();

    // store all answers
    vector<int> result;

    // for each query x
    for (int x : queries) {

        // index to print (1-based), 0 if not found
        int idx = 0;

        // find first index where A[i] >= x
        for (int i = 0; i < n; i++) {
            if (A[i] >= x) {

                // store 1-based index
                idx = i + 1;

                // decrease value
                A[i] -= x;

                // stop search
                break;
            }
        }

        // record the answer
        result.push_back(idx);
    }

    return result;
}

int main() {

    vector<int> A = {3, 2, 4, 1, 5, 5, 2, 6};

   
    vector<int> queries = {4, 4, 7, 1, 1};

    vector<int> res = processQueries(A, queries);

    for (int x : res)
        cout << x << " ";
    cout << endl;

    return 0;
}
Java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

class GFG {
    
    static ArrayList<Integer> processQueries(int[] A, int[] queries) {

        // array size
        int n = A.length;

        // store all answers
        ArrayList<Integer> result = new ArrayList<>();

        // for each query x
        for (int x : queries) {

            // index to print (1-based), 0 if not found
            int idx = 0;

            // find first index where A[i] >= x
            for (int i = 0; i < n; i++) {
                if (A[i] >= x) {

                    // store 1-based index
                    idx = i + 1;

                    // decrease value
                    A[i] = A[i] - x;

                    // stop search
                    break;
                }
            }

            // record answer
            result.add(idx);
        }

        return result;
    }

    public static void main(String[] args) {

        int[] A = {3, 2, 4, 1, 5, 5, 2, 6};

        int[] queries = {4, 4, 7, 1, 1};

        ArrayList<Integer> res = processQueries(A, queries);

        for (int x : res)
            System.out.print(x + " ");
        System.out.println();
    }
}
Python
def processQueries(A, queries):

    # array size
    n = len(A)

    # store all answers
    result = []

    # for each query x
    for x in queries:

        # index to print (1-based), 0 if not found
        idx = 0

        # find first index where A[i] >= x
        for i in range(n):
            if A[i] >= x:

                # store 1-based index
                idx = i + 1

                # decrease value
                A[i] -= x

                # stop search
                break

        # record the answer
        result.append(idx)

    return result


if __name__ == "__main__":


    A = [3, 2, 4, 1, 5, 5, 2, 6]

   
    queries = [4, 4, 7, 1, 1]

    res = processQueries(A, queries)

    print(*res)
C#
using System;
using System.Collections.Generic;

class GFG {

    static List<int> processQueries(int[] A, int[] queries) {

        // array size
        int n = A.Length;

        // store all answers
        List<int> result = new List<int>();

        // for each query x
        foreach (int x in queries) {

            // index to print (1-based), 0 if not found
            int idx = 0;

            // find first index where A[i] >= x
            for (int i = 0; i < n; i++) {
                if (A[i] >= x) {

                    // store 1-based index
                    idx = i + 1;

                    // decrease value
                    A[i] -= x;

                    // stop search
                    break;
                }
            }

            // record the answer
            result.Add(idx);
        }

        return result;
    }

    static void Main() {

        int[] A = { 3, 2, 4, 1, 5, 5, 2, 6 };

        int[] queries = { 4, 4, 7, 1, 1 };

        List<int> res = processQueries(A, queries);

        foreach (int x in res)
            Console.Write(x + " ");
        Console.WriteLine();
    }
}
JavaScript
function processQueries(A, queries) {

    // array size
    const n = A.length;

    // store all answers
    const result = [];

    // for each query x
    for (const x of queries) {

        // index to print (1-based), 0 if not found
        let idx = 0;

        // find first index where A[i] >= x
        for (let i = 0; i < n; i++) {
            if (A[i] >= x) {

                // store 1-based index
                idx = i + 1;

                // decrease value
                A[i] -= x;

                // stop search
                break;
            }
        }

        // record the answer
        result.push(idx);
    }

    return result;
}

// Driver code
const A = [3, 2, 4, 1, 5, 5, 2, 6];


const queries = [4, 4, 7, 1, 1];

const res = processQueries(A, queries);

console.log(...res);

Output
3 5 0 1 1 

[Expected Approach] Using Segment Tree - O((n + q) log n) Time and O(n) Space

The idea is to use a segment tree to efficiently locate the first index whose value is at least x. The tree stores the maximum value in each range, allowing us to immediately determine if any element satisfies the requirement. If the range contains such an element, we recursively search the correct subtree to find the smallest valid index. After selecting the index, we reduce its value by x and update the segment tree so future queries remain accurate. This avoids scanning the entire array each time and provides a fast, scalable method for large arrays.

C++
#include <iostream>
#include <vector>
using namespace std;

// build segment tree storing max in each range
void buildTree(int idx, int l, int r, vector<int> &seg, vector<int> &A) {

    // leaf node stores single value
    if (l == r) {
        seg[idx] = A[l];
        return;
    }

    // find midpoint
    int mid = (l + r) / 2;

    // build left subtree
    buildTree(2 * idx, l, mid, seg, A);

    // build right subtree
    buildTree(2 * idx + 1, mid + 1, r, seg, A);

    // parent stores maximum of children
    seg[idx] = max(seg[2 * idx], seg[2 * idx + 1]);
}

// find first index i such that A[i] >= x
int findFirst(int idx, int l, int r, vector<int> &seg, int x) {

    // if max of segment < x then no index is valid
    if (seg[idx] < x)
        return -1;

    // if leaf, we found the index
    if (l == r)
        return l;

    // compute midpoint
    int mid = (l + r) / 2;

    // search left side first for minimum index
    if (seg[2 * idx] >= x)
        return findFirst(2 * idx, l, mid, seg, x);

    // otherwise search right side
    return findFirst(2 * idx + 1, mid + 1, r, seg, x);
}

// update A[pos] = newVal in segment tree
void updateTree(int idx, int l, int r, vector<int> &seg, int pos, int newVal) {

    // base: single index
    if (l == r) {
        seg[idx] = newVal;
        return;
    }

    // midpoint
    int mid = (l + r) / 2;

    // update correct child
    if (pos <= mid)
        updateTree(2 * idx, l, mid, seg, pos, newVal);
    else
        updateTree(2 * idx + 1, mid + 1, r, seg, pos, newVal);

    // merge updated children
    seg[idx] = max(seg[2 * idx], seg[2 * idx + 1]);
}

// process all queries using segment tree
vector<int> processQueries(vector<int> &A, vector<int> &queries) {

    int n = A.size();

    // segment tree for max
    vector<int> seg(4 * n);

    // build initial tree
    buildTree(1, 0, n - 1, seg, A);

    vector<int> result;

    // process each query x
    for (int x : queries) {

        // check if any element >= x exists
        if (seg[1] < x) {
            result.push_back(0);
            continue;
        }

        // find first valid index
        int pos = findFirst(1, 0, n - 1, seg, x);

        // reduce A[pos] by x
        A[pos] -= x;

        // update segment tree
        updateTree(1, 0, n - 1, seg, pos, A[pos]);

        // store 1-based index
        result.push_back(pos + 1);
    }

    return result;
}

int main() {

    vector<int> A = {3, 2, 4, 1, 5, 5, 2, 6};

    vector<int> queries = {4, 4, 7, 1, 1};

    vector<int> res = processQueries(A, queries);

    for (int x : res)
        cout << x << " ";
    cout << endl;

    return 0;
}
Java
import java.util.ArrayList;

class GFG {

    // build segment tree storing max values
    static void buildTree(int idx, int l, int r, int[] seg, int[] A) {
        if (l == r) {
            seg[idx] = A[l];
            return;
        }
        int mid = (l + r) / 2;
        buildTree(2 * idx, l, mid, seg, A);
        buildTree(2 * idx + 1, mid + 1, r, seg, A);
        seg[idx] = Math.max(seg[2 * idx], seg[2 * idx + 1]);
    }

    // find first index i such that A[i] >= x
    static int findFirst(int idx, int l, int r, int[] seg, int x) {
        if (seg[idx] < x)
            return -1;

        if (l == r)
            return l;

        int mid = (l + r) / 2;

        if (seg[2 * idx] >= x)
            return findFirst(2 * idx, l, mid, seg, x);

        return findFirst(2 * idx + 1, mid + 1, r, seg, x);
    }

    // update A[pos] = newVal in segment tree
    static void updateTree(int idx, int l, int r, int[] seg, int pos, int newVal) {
        if (l == r) {
            seg[idx] = newVal;
            return;
        }

        int mid = (l + r) / 2;

        if (pos <= mid)
            updateTree(2 * idx, l, mid, seg, pos, newVal);
        else
            updateTree(2 * idx + 1, mid + 1, r, seg, pos, newVal);

        seg[idx] = Math.max(seg[2 * idx], seg[2 * idx + 1]);
    }

    // process queries and return ArrayList
    static ArrayList<Integer> processQueries(int[] A, int[] queries) {

        int n = A.length;
        int[] seg = new int[4 * n];

        buildTree(1, 0, n - 1, seg, A);

        ArrayList<Integer> result = new ArrayList<>();

        for (int x : queries) {

            if (seg[1] < x) {
                result.add(0);
                continue;
            }

            int pos = findFirst(1, 0, n - 1, seg, x);

            A[pos] -= x;

            updateTree(1, 0, n - 1, seg, pos, A[pos]);
            
             // return 1-based index
            result.add(pos + 1);
        }

        return result;
    }

    public static void main(String[] args) {

        int[] A = {3, 2, 4, 1, 5, 5, 2, 6};
        int[] queries = {4, 4, 7, 1, 1};

        ArrayList<Integer> res = processQueries(A, queries);

        for (int x : res)
            System.out.print(x + " ");
        System.out.println();
    }
}
Python
# build segment tree storing max values
def build_tree(idx, l, r, seg, A):

    # leaf node
    if l == r:
        seg[idx] = A[l]
        return

    # midpoint
    mid = (l + r) // 2

    # build left subtree
    build_tree(2 * idx, l, mid, seg, A)

    # build right subtree
    build_tree(2 * idx + 1, mid + 1, r, seg, A)

    # parent stores max of children
    seg[idx] = max(seg[2 * idx], seg[2 * idx + 1])


# find first index i such that A[i] >= x
def find_first(idx, l, r, seg, x):

    # no valid index
    if seg[idx] < x:
        return -1

    # leaf found
    if l == r:
        return l

    # midpoint
    mid = (l + r) // 2

    # search left subtree
    if seg[2 * idx] >= x:
        return find_first(2 * idx, l, mid, seg, x)

    # otherwise search right
    return find_first(2 * idx + 1, mid + 1, r, seg, x)


# update A[pos] = newVal
def update_tree(idx, l, r, seg, pos, val):

    # leaf node
    if l == r:
        seg[idx] = val
        return

    # midpoint
    mid = (l + r) // 2

    # update correct child
    if pos <= mid:
        update_tree(2 * idx, l, mid, seg, pos, val)
    else:
        update_tree(2 * idx + 1, mid + 1, r, seg, pos, val)

    # update parent max
    seg[idx] = max(seg[2 * idx], seg[2 * idx + 1])


# process all queries
def processQueries(A, queries):

    n = len(A)

    # segment tree
    seg = [0] * (4 * n)

    # build initial tree
    build_tree(1, 0, n - 1, seg, A)

    result = []

    # process each value x
    for x in queries:

        # no valid index
        if seg[1] < x:
            result.append(0)
            continue

        # find first valid index
        pos = find_first(1, 0, n - 1, seg, x)

        # update array
        A[pos] -= x

        # update seg tree
        update_tree(1, 0, n - 1, seg, pos, A[pos])

        # append 1-based index
        result.append(pos + 1)

    return result


if __name__ == "__main__":

  
    A = [3, 2, 4, 1, 5, 5, 2, 6]

  
    queries = [4, 4, 7, 1, 1]

    res = processQueries(A, queries)

    print(*res)
C#
using System;
using System.Collections.Generic;

class GFG {

    // build segment tree storing max values
    static void buildTree(int idx, int l, int r, int[] seg, int[] a) {

        if (l == r) {
            seg[idx] = a[l];
            return;
        }

        int mid = (l + r) / 2;

        buildTree(2 * idx, l, mid, seg, a);
        buildTree(2 * idx + 1, mid + 1, r, seg, a);

        seg[idx] = Math.Max(seg[2 * idx], seg[2 * idx + 1]);
    }

    // find first index such that A[i] >= x
    static int findFirst(int idx, int l, int r, int[] seg, int x) {

        if (seg[idx] < x)
            return -1;

        if (l == r)
            return l;

        int mid = (l + r) / 2;

        if (seg[2 * idx] >= x)
            return findFirst(2 * idx, l, mid, seg, x);

        return findFirst(2 * idx + 1, mid + 1, r, seg, x);
    }

    // update A[pos] = val
    static void updateTree(int idx, int l, int r, int[] seg, int pos, int val) {

        if (l == r) {
            seg[idx] = val;
            return;
        }

        int mid = (l + r) / 2;

        if (pos <= mid)
            updateTree(2 * idx, l, mid, seg, pos, val);
        else
            updateTree(2 * idx + 1, mid + 1, r, seg, pos, val);

        seg[idx] = Math.Max(seg[2 * idx], seg[2 * idx + 1]);
    }

    // process all queries (returns List<int>)
    static List<int> processQueries(int[] a, int[] queries) {

        int n = a.Length;

        int[] arr = new int[n];
        Array.Copy(a, arr, n);

        int[] seg = new int[4 * n];

        buildTree(1, 0, n - 1, seg, arr);

        List<int> result = new List<int>();

        foreach (int x in queries) {

            if (seg[1] < x) {
                result.Add(0);
                continue;
            }

            int pos = findFirst(1, 0, n - 1, seg, x);

            arr[pos] -= x;

            updateTree(1, 0, n - 1, seg, pos, arr[pos]);

            result.Add(pos + 1);
        }

        return result;
    }

    static void Main() {

        int[] a = {3, 2, 4, 1, 5, 5, 2, 6};
        int[] queries = {4, 4, 7, 1, 1};

        var res = processQueries(a, queries);

        Console.WriteLine(string.Join(" ", res));
    }
}
JavaScript
// build segment tree storing max values
function buildTree(idx, l, r, seg, A) {

    // leaf node
    if (l === r) {
        seg[idx] = A[l];
        return;
    }

    // midpoint
    let mid = Math.floor((l + r) / 2);

    // build left subtree
    buildTree(2 * idx, l, mid, seg, A);

    // build right subtree
    buildTree(2 * idx + 1, mid + 1, r, seg, A);

    // parent stores max of children
    seg[idx] = Math.max(seg[2 * idx], seg[2 * idx + 1]);
}

// find first index with A[i] >= x
function findFirst(idx, l, r, seg, x) {

    // no valid index
    if (seg[idx] < x) return -1;

    // leaf found
    if (l === r) return l;

    // midpoint
    let mid = Math.floor((l + r) / 2);

    // search left side
    if (seg[2 * idx] >= x)
        return findFirst(2 * idx, l, mid, seg, x);

    // search right side
    return findFirst(2 * idx + 1, mid + 1, r, seg, x);
}

// update A[pos] = val
function updateTree(idx, l, r, seg, pos, val) {

    // leaf node
    if (l === r) {
        seg[idx] = val;
        return;
    }

    // midpoint
    let mid = Math.floor((l + r) / 2);

    // update correct child
    if (pos <= mid)
        updateTree(2 * idx, l, mid, seg, pos, val);
    else
        updateTree(2 * idx + 1, mid + 1, r, seg, pos, val);

    // update parent
    seg[idx] = Math.max(seg[2 * idx], seg[2 * idx + 1]);
}

// process all queries
function processQueries(A, queries) {

    const n = A.length;

    // segment tree
    const seg = new Array(4 * n).fill(0);

    // build initial tree
    buildTree(1, 0, n - 1, seg, A);

    const result = [];

    // process each query x
    for (let x of queries) {

        // no valid index
        if (seg[1] < x) {
            result.push(0);
            continue;
        }

        // find first valid index
        let pos = findFirst(1, 0, n - 1, seg, x);

        // update value
        A[pos] -= x;

        // update tree
        updateTree(1, 0, n - 1, seg, pos, A[pos]);

        // store 1-based index
        result.push(pos + 1);
    }

    return result;
}

// Driver code
let A = [3, 2, 4, 1, 5, 5, 2, 6];
let queries = [4, 4, 7, 1, 1];

let res = processQueries(A, queries);
console.log(...res);

Output
3 5 0 1 1 



Article Tags :

Explore