# Square Root (Sqrt) Decomposition Algorithm

## Introduction to Square Root Decomposition

The clever Square Root Decomposition algorithm divides an array or data structure into smaller blocks in order to optimise a number of issues. This approach is particularly helpful because it strikes a balance between precomputation and real-time computation when dealing with queries or updates involving specific ranges of array elements.

### Recognising the Fundamentals

Sqrt Decomposition Algorithm: What Is It?

The Sqrt Decomposition algorithm, at its core, splits an array into blocks of approximately equal size, each of which contains the sum, minimum, maximum, or any other necessary information about the elements within that block. This precomputation enables effective query processing and update operations on array subranges.

### Applying the Algorithm

The Sqrt Decomposition algorithm's aptitude for effectively handling range updates and queries is one of its main advantages. The algorithm excels when asked to find the sum, minimum, maximum, or any other operation across a range of array elements. Such operations' time complexity is decreased from O(N) to O(N).

Complexity Analysis

The Sqrt Decomposition algorithm's time complexity varies depending on the problem being solved. Preprocessing the block values typically takes O(N) time. O(N) time is required for each query o update to be answered or completed. When handling a large number of queries, this trade-off between preprocessing time and query/update time is especially helpful.

### Steps for Implementation

Block division of the Array

By dividing the array into blocks of roughly equal size, the Sqrt Decomposition algorithm can be implemented in two steps. With the possible exception of the final block, each block will contain N elements.

After the array has been split up into blocks, pre-calculate the necessary values for each block. Each block would be used to store the sum of its elements, for instance, if the issue involves range sum queries.

Responding to Questions Quickly

It is possible to decompose a query or update operation into actions on the precomputed block values when it is received. The algorithm locates the pertinent blocks for a query involving a range and combines their precomputed values to produce the result.

### Applications in the Real World

Range Sum Inquiry

The Sqrt Decomposition algorithm is frequently used for efficiently resolving range sum problems. The algorithm can preprocess the sum of elements in each block of an array and use this knowledge to respond to requests for the sum of elements within a specified range.

Identifying a range's minimum or maximum

Finding the minimum or maximum element within a range of array elements is another useful application. The algorithm can quickly respond to such questions by computing the minimum and maximum values for each block beforehand.

• Query Efficiency: The algorithm greatly enhances query performance, bringing down the time complexity to O(N).
• Update operations can also be efficiently performed by optimising them, keeping the balance between query and update times.
• Simple Implementation: Compared to other complex data structures, the algorithm's implementation is frequently more straightforward.
• Memory Efficiency: It uses less memory than some alternatives, making it appropriate for situations where memory is limited.

Limitations to Consider

• Specific Problem Set: Sqrt Decomposition works best for range queries and updates problems.
• Trade-off for Block Size: It is important to think carefully when selecting the block size because smaller blocks speed up preprocessing but reduce query efficiency.

### Comparison with Other Techniques

Sqrt Decomposition vs. Segment Trees

Another well-liked data structure for dealing with range updates and queries is the segment tree. While Sqrt Decomposition is typically easier to implement and uses less memory than Segment Trees, they both offer greater versatility and the ability to handle a wider range of issues.

Cons and Benefits Compared to Binary Indexed Trees

For comparable tasks, Binary Indexed Trees (BIT) are also employed. Sqrt Decomposition provides better cache locality, which speeds it up for some issues. BIT, on the other hand, uses less room.

Python code:

Output:

```Sum of elements in range [2, 5]: 18
```

Here's an explanation of the code:

1. The sqrt_decomposition function takes an array arr as input and divides it into blocks based on the square root decomposition approach. The number of blocks and the size of each block are determined.
2. The blocks are represented as a list of lists called blocks. Each sub-list corresponds to a block and contains the elements within that block.
3. The preprocess_blocks function takes the blocks list and calculates the sum of elements in each block. The block sums are stored in the block_sums
4. The query_sum function takes the block_sums list, the original array arr, and range indices l and r to compute the sum of elements within the specified range.
5. The function iterates through the blocks that overlap with the range [l, r]. For each block, it checks if the entire block is within the range. If yes, it adds the precomputed block sum to the total_sum. Otherwise, it iterates through the individual elements within the block that partially overlap with the range and adds their values to the total_sum.
6. In the example usage section, an example array arr is defined. The array is divided into blocks using the sqrt_decomposition function, and the block sums are preprocessed using the preprocess_blocks
7. A query is made using the query_sum function to find the sum of elements in the range [2, 5] of the original array. The result is printed.