Skip to content

Commit a71ed0c

Browse files
authored
Merge pull request #1459 from divyalakshmi0/main
Added Mo's Algorithm for Efficient Range Queries
2 parents e059301 + 430ac4d commit a71ed0c

File tree

2 files changed

+154
-0
lines changed

2 files changed

+154
-0
lines changed

1D Arrays/Mo's Algorithm/Program.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <math.h>
4+
5+
#define MAX_N 100000
6+
#define MAX_Q 100000
7+
8+
// Structure for each query
9+
typedef struct {
10+
int L, R, idx;
11+
} Query;
12+
13+
int n, q;
14+
int arr[MAX_N];
15+
Query queries[MAX_Q];
16+
int answer[MAX_Q];
17+
int current_answer = 0;
18+
int freq[1000001];
19+
20+
// Comparator function to sort queries by Mo's ordering
21+
int compare(const void *a, const void *b) {
22+
Query *q1 = (Query *)a;
23+
Query *q2 = (Query *)b;
24+
int block1 = q1->L / (int)sqrt(n);
25+
int block2 = q2->L / (int)sqrt(n);
26+
if (block1 != block2) {
27+
return block1 - block2;
28+
}
29+
return (block1 & 1) ? (q1->R - q2->R) : (q2->R - q1->R);
30+
}
31+
32+
// Function to add element at index pos
33+
void add(int pos) {
34+
current_answer += arr[pos];
35+
}
36+
37+
// Function to remove element at index pos
38+
void remove(int pos) {
39+
current_answer -= arr[pos];
40+
}
41+
42+
// Mo's Algorithm to answer all queries
43+
void mo_algorithm() {
44+
int currentL = 0, currentR = -1;
45+
for (int i = 0; i < q; i++) {
46+
int L = queries[i].L;
47+
int R = queries[i].R;
48+
49+
// Adjust the left boundary
50+
while (currentL < L) {
51+
remove(currentL);
52+
currentL++;
53+
}
54+
while (currentL > L) {
55+
currentL--;
56+
add(currentL);
57+
}
58+
59+
// Adjust the right boundary
60+
while (currentR < R) {
61+
currentR++;
62+
add(currentR);
63+
}
64+
while (currentR > R) {
65+
remove(currentR);
66+
currentR--;
67+
}
68+
69+
// Store the answer for this query
70+
answer[queries[i].idx] = current_answer;
71+
}
72+
}
73+
74+
int main() {
75+
// Input array size and elements
76+
printf("Enter the size of the array: ");
77+
scanf("%d", &n);
78+
for (int i = 0; i < n; i++) {
79+
scanf("%d", &arr[i]);
80+
}
81+
82+
// Input number of queries and their ranges
83+
printf("Enter the number of queries: ");
84+
scanf("%d", &q);
85+
for (int i = 0; i < q; i++) {
86+
scanf("%d %d", &queries[i].L, &queries[i].R);
87+
queries[i].L--; // Convert to zero-based indexing
88+
queries[i].R--;
89+
queries[i].idx = i;
90+
}
91+
92+
// Sort queries according to Mo's ordering
93+
qsort(queries, q, sizeof(Query), compare);
94+
95+
// Execute Mo's Algorithm
96+
mo_algorithm();
97+
98+
// Output the answers for each query
99+
printf("Query Results:\n");
100+
for (int i = 0; i < q; i++) {
101+
printf("Query %d: %d\n", i + 1, answer[i]);
102+
}
103+
104+
return 0;
105+
}

1D Arrays/Mo's Algorithm/Readme.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Mo's Algorithm for Efficient Range Queries
2+
3+
## Description
4+
5+
Mo's Algorithm is a powerful offline algorithm used to efficiently answer multiple range queries on a static array. It optimizes query processing by organizing overlapping range queries and reducing redundant calculations, making it particularly useful for datasets where frequent range queries need to be resolved without modifying the array.
6+
7+
## Key Features
8+
- **Block Decomposition**: The array is divided into blocks of size √N, where N is the array length. This reduces redundant calculations by allowing queries in each block to share some computed values.
9+
- **Query Optimization**: Queries are sorted based on block indices and processed in a specific order to maximize efficiency.
10+
- **Efficient Range Queries**: Mo's Algorithm is versatile for various types of range queries, including sum, frequency, and XOR operations.
11+
12+
## Problem Definition
13+
14+
Given an array and multiple range queries, each asking for a specific calculation (e.g., sum or XOR) over a subarray, the goal is to answer each query as efficiently as possible.
15+
16+
- **Input**:
17+
- An array of integers.
18+
- Multiple range queries, each specifying a start and end index.
19+
- **Output**: An efficient way to answer each query with reduced computation time.
20+
21+
## Algorithm Review
22+
23+
### 1. Initialization
24+
- Divide the array into blocks of size √N, where N is the number of elements in the array.
25+
- Sort the queries based on the block of their starting index (or both start and end indices if within the same block).
26+
27+
### 2. Query Processing
28+
- Process each query by adjusting a current range of indices, only moving elements in or out of the range as needed:
29+
- **Move Left or Right**: Adjust the range to the new query range.
30+
- **Update Computation**: Recompute the necessary values, adding or removing elements as required.
31+
32+
### 3. Sorting and Efficiency
33+
- Sorting the queries enables minimizing movement, which optimizes calculations as shared values can be reused.
34+
35+
## Complexity Analysis
36+
37+
- **Time Complexity**: O((N + Q) * √N), where N is the length of the array and Q is the number of queries.
38+
- **Space Complexity**: O(N), for storing additional data structures and arrays.
39+
40+
## Applications
41+
42+
Mo's Algorithm is valuable in scenarios involving multiple range queries, such as:
43+
- **Competitive Programming**: Optimizing repeated range queries on static arrays.
44+
- **Data Analysis**: Quickly calculating aggregates (like sum or frequency) over specified ranges in datasets.
45+
- **Image and Signal Processing**: For tasks that require overlapping range queries on static data.
46+
47+
## Conclusion
48+
49+
Mo's Algorithm is an efficient way to handle overlapping range queries on large datasets with static arrays. Its block decomposition and query ordering make it ideal for applications requiring numerous range queries where direct recomputation would be too slow. Understanding and implementing Mo's Algorithm enhances one’s ability to manage complex range queries efficiently in various fields, especially in competitive programming and data analysis.

0 commit comments

Comments
 (0)