Block-based interval modification and single-point query, Interval Single-point Query
A series with a length of n and n operations are provided. operations involve interval addition and single point query value.
This is a classic question that can optimize many data structures and can be used for training different data structures.
A series is to package every m element in the series to optimize the algorithm.
For example, if we divide every m elements into n/m blocks, each timeThe interval addition operation involves the entire O (n/m) block and up to 2 m elements in two incomplete blocks on both sides of the interval.
We set an addition tag for each block (that is, to record the number of elements added together in the block). Each operation directly marks the entire block with O (1, the incomplete blocks force modify the value of the element because there are few elements.
The value of the returned element is added with the addition tag of the block.
In this way, the complexity of each operation is O (n/m) + O (m). According to the mean inequality, when m is √ n, the total complexity is the lowest. For convenience, by default, the following part size is √ n.
Interval Addition
1 void interval_add (int ll, int rr, int v) 2 {3 for (int I = ll; I <= min (where [ll] * m, rr ); I ++) 4 // The result is that where [ll] is not a complete block, that is, ll is on the rightmost side of the actual block, 5 // then facilitate ll-the end of the block/rr, and add 6 a [I] + = v; 7 if (where [ll]! = Where [rr]) 8 // note that if ll and rr are in the same block, the above side has been added, so do not add 9 {10 for (int I = (where [rr]-1) * m; I <= rr; I ++) 11 // here, the rr is located on the rightmost left side of the actual block. 12 // where [I] * m indicates the rightmost element of block I. 13/ /where [rr]-1 is the rightmost element of the block on the left of the rr Block 14 // until the rr brute force increase by 15 a [I] + = v; 16} 17 for (int I = where [ll] + 1; I <= where [rr]-1; I ++) 18 // here, where [ll] and where [rr] have been handled violently, so you can add [I] + = v; 20} Only by enumerating the middle blocks}
Single point Query
1 printf ("% d \ n", a [v] + add [where [v]);
Complete code
1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <cmath> 5 using namespace std; 6 const int MAXN = 100001; 7 int n, q, m, how, l, r, v; 8 int a [MAXN]; // The initial value is 9 int add [MAXN]; // The value added to each block is 10 int where [MAXN]; // record the number of each value corresponding to the 11 void interval_add (int ll, int rr, int v) 12 {13 for (int I = ll; I <= min (where [ll] * m, rr); I ++) 14 // here we determine that where [ll] is an incomplete block, that is, ll is on the right of the leftmost end of the actual block, 15 // then facilitate ll-the end of the block/rr, the violent increase of 16 a [I] + = V; 17 if (where [ll]! = Where [rr]) 18 // note that if ll and rr are in the same block, the above side has been added, so do not add 19 {20 for (int I = (where [rr]-1) * m; I <= rr; I ++) 21 // here, the rr is located on the rightmost left side of the actual block. 22 // where [I] * m indicates the rightmost element of block I. 23/ /where [rr]-1 is the rightmost element of the block on the left of the rr block 24 // until the rr violent increase of 25 a [I] + = v; 26} 27 for (int I = where [ll] + 1; I <= where [rr]-1; I ++) 28 // here, both where [ll] and where [rr] have been handled violently. Therefore, you can add [I] + = v to enumerate only the middle blocks; 30} 31 int main () 32 {33 scanf ("% d", & n); 34 m = sqrt (n); 35 for (int I = 1; I <= n; I ++) 36 scanf ("% d", & a [I]); 37 for (int I = 1; I <= n; I ++) 38 where [I] = (I-1)/m + 1; // here I can-1 (hzwer writes-1) can also not write, if this parameter is left blank, the number of elements in the first block will be expressed as S-1 39 scanf ("% d", & q); 40 for (int I = 1; I <= q; I ++) 41 {42 scanf ("% d", & how); 43 if (how = 1) // Add 44 {45 scanf ("% d ", & l, & r, & v); 46 interval_add (l, r, v); 47} 48 else // Single Point query 49 {50 scanf ("% d ", & v); 51 printf ("% d \ n", a [v] + add [where [v]); 52 // where stores the block to which the vertex belongs. add indicates that the added element 53 // a [v] of the block is the starting value of this vertex, one plus is answer 54} 55} 56 return 0; 57}