Introduction¶
Blocking problem is pretty common in OI. In fact, blocking is more of a way of thinking than a data structure.
From NOIP to NOI to IOI, the blocking idea has appeared in all kinds of difficulty levels.
The common blocking algorithms have a root time complexity, while some may have the complexity other than
Blocking is a very flexible idea. Almost everything can be divided into blocks, and it is not difficult to implement.
You can write whatever data structure you want. However, the disadvantage is that the time complexity is not good enough.
Of course, when the constant is small (e.g.
By no means is this suggesting that we should use blocking. In OI, it can be used as a backup plan. The first choice must be advanced data structures such as segment trees.
Here are a few examples:
Interval sum¶
Motivation: The segment tree might be a bit difficult to implement?
For a sequence of length
We maintain the interval sum of each segment. Each time we mark the entire segment in
Each time we query the interval, it returns the element value plus the mark added on its segment. So the overall time complexity is
Operations involved in the process of interval modification include single node modification, interval modification(marking & brute force modification), and interval query.
When
Here we offer the C++ implementaion of interval query. The complete template is still WIP;
// ...
#define LL long long
const LL MAXN=100001;
LL a[MAXN]; // initial value
LL add[MAXN]; // value added to each segment
LL location[MAXN]; // which segment
LL sum[MAXN]; // sum of each segment
// ...
void interval_query(LL ll, LL rr)
{
LL res=0;
for(LL i = ll; i <= min(location[ll] * T, rr); i++)
res += a[i] + add[location[i]];
if(location[ll] != location[rr])
for(LL i = (location[rr]-1) * T+1; i<=rr; i++)
res += a[i] + add[location[i]];
for(LL i = location[ll] + 1; i <= location[rr]-1; i++)
res += sum[i]+add[i] * T;
printf("%lld\n", res);
}
Interval sum 2¶
The time complexity of the previous approach is
Here we introduce an algorithm in
For
However, in the case of modification, it is not convenient to maintain, and only the prefix sum in a single block can be maintained.
Then, take each block as a unit and calculate prefix sums for them.
Modify takes
Query: There are three parts involved, each part can be directly obtained by prefix sum. The time complexity is
Making query blocks¶
The same problem, now the sequence length is
If the number of operations is relatively small, we can record and add them when querying.
Assume that at most
After
Total time complexity:
When
Reference¶
- Introduction to blocking method (Original link in Chinese)
- Blocking problem intro (Original link in Chinese)
buildLast update and/or translate time of this article,Check the history
editFound smelly bugs? Translation outdated? Wanna contribute with us? Edit this Page on Github
peopleContributor of this article Ir1d, HeRaNO, Xeonacid
translateTranslator of this article Visit the original article!
copyrightThe article is available under CC BY-SA 4.0 & SATA ; additional terms may apply.