-
Notifications
You must be signed in to change notification settings - Fork 156
Add tutorial for LOJ-1164 Horrible Queries #473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
73a6b01
LOJ-1041 updated
Evan-CSE e1c1676
Add tutorial for LOJ-1041 Road Construction #407
Evan-CSE 75fed93
Resolved issues
Evan-CSE c6cc5a3
Feedback accepted
Evan-CSE afc113a
Add tutorial for LOJ-1164 Horrible Queries #471
Evan-CSE d12672b
Merge branch 'tutorialFor1164'
Evan-CSE 00765fa
Changes as per PR comments
Evan-CSE File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
# LOJ-1164: Horrible Queries | ||
|
||
## Prerequisite: | ||
- [Segment Tree](https://cp-algorithms.com/data_structures/segment_tree.html) | ||
- [Lazy Propagation](https://www.topcoder.com/thrive/articles/range-operations-lazy-propagation) | ||
|
||
## Problem at a glance: | ||
In this problem we are required to perform two kinds of operation. | ||
1. Update a range by a given `value` | ||
2. Find the total sum of given range | ||
|
||
## Approach | ||
Its clear that we can use `cumulative sum` to answer the second type of query. However, updating a range of values using this approach would have a time complexity of **O(n)**, which could lead to a **"Time Limit Exceeded" (TLE)** error for larger inputs. If you are already familiar with **segment tree** then you can start with segment tree. But unlike segment tree we are required to **update range** which may lead to **TLE** To solve this problem we can use a variation of **segment tree** called **lazy propagation** | ||
|
||
## Lazy Propagation at a glance | ||
Lazy propagation is an optimization technique used with segment trees. If you are not familiar with segment trees, it is recommended to learn about them before proceeding. | ||
|
||
With lazy propagation, instead of updating a range instantly, we only mark the root node of that range for future updates. We maintain an extra array to keep track of which nodes need to be updated. Here's an illustration: | ||
|
||
 | ||
|
||
Let's say we want to update the range [4:6]. The root node of this range is the 3rd node. Rather than updating all the nodes below [4:6] immediately, we simply mark the immediate children of the 3rd node with a value that should be added in the future. Our second array tracks this information for each node to determine if its child nodes should be updated or not. When we need to query or update the range again, we will update the specific node. | ||
|
||
You will have a better understanding of this concept as you read through the tutorial. It's a straightforward problem if you can understand both the segment tree and lazy propagation algorithms. | ||
|
||
### Code | ||
|
||
``` | ||
#include<bits/stdc++.h> | ||
|
||
using namespace std; | ||
|
||
|
||
#define endl "\n" | ||
#define MAX 400010 | ||
|
||
|
||
long long segSum[MAX], lazy[MAX]; | ||
|
||
void clearAll() { | ||
for (int i = 0; i < MAX; i++) { | ||
segSum[i] = 0; | ||
lazy[i] = 0; | ||
} | ||
} | ||
|
||
|
||
void update(int node, long long leftTree, long long rightTree, long long left, long long right, long long value) { | ||
int leftSide = node * 2; | ||
int rightSide = (node * 2) + 1; | ||
if (lazy[node]) { | ||
segSum[node] += ((rightTree - leftTree + 1) * lazy[node]); | ||
if (leftTree != rightTree) { | ||
lazy[leftSide] += lazy[node]; | ||
lazy[rightSide] += lazy[node]; | ||
} | ||
lazy[node] = 0; | ||
} | ||
if (leftTree > right || rightTree < left) { | ||
return; | ||
} | ||
if (leftTree >= left && rightTree <= right) { | ||
segSum[node] += ((rightTree - leftTree + 1) * value); | ||
if (leftTree != rightTree) { | ||
lazy[leftSide] += value; | ||
lazy[rightSide] += value; | ||
} | ||
return; | ||
} | ||
int mid = (leftTree + rightTree) >> 1; | ||
update(leftSide, leftTree, mid, left, right, value); | ||
update(rightSide, mid + 1, rightTree, left, right, value); | ||
segSum[node] = segSum[leftSide] + segSum[rightSide]; | ||
} | ||
|
||
|
||
long long query(int node, long long lt, long long rt, long long l, long long r) { | ||
int leftSide = node * 2; | ||
int rightSide = (node * 2) + 1; | ||
if (lazy[node]) { | ||
segSum[node] += ((rt - lt + 1) * lazy[node]); | ||
if (lt != rt) { | ||
lazy[leftSide] += lazy[node]; | ||
lazy[rightSide] += lazy[node]; | ||
} | ||
lazy[node] = 0; | ||
} | ||
if (lt > r || rt < l) { | ||
return 0; | ||
} | ||
if (l <= lt && rt <= r) { | ||
return segSum[node]; | ||
} | ||
int mid = (lt + rt) >> 1; | ||
long long leftSum = query(leftSide, lt, mid, l, r); | ||
long long rightSum = query(rightSide, mid + 1, rt, l, r); | ||
return leftSum + rightSum; | ||
} | ||
|
||
|
||
int main() { | ||
int t, cs = 1; | ||
cin >> t; | ||
while (t--) { | ||
int n,q; | ||
cin >> n >> q; | ||
clearAll(); | ||
cout <<"Case "<< cs++ << ":\n"; | ||
while(q--) { | ||
int choice, left, right; | ||
cin >> choice >> left >> right; | ||
if (choice == 0) { | ||
long long value; | ||
cin >> value; | ||
update(1, 0, n - 1, left, right, value); | ||
} | ||
else { | ||
cout << query(1, 0, n - 1, left, right) <<endl; | ||
} | ||
} | ||
} | ||
return 0; | ||
} | ||
``` | ||
|
||
|
||
### Tutorial by: | ||
Profile Link: [Hasibur Rahman](https://lightoj.com/user/evan13) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.