Optimal_Aces's blog

By Optimal_Aces, history, 5 years ago, In English
  • Vote: I like it
  • 0
  • Vote: I do not like it

| Write comment?
»
5 years ago, # |
  Vote: I like it +8 Vote: I do not like it

For future reference, you should explain how you've attempted to solve a problem you're asking about, as it feels more personal and you'll probably get more help.

This problem can be easily 'cheesed' with a segment tree of size $$$2q$$$. Keep a pointer to the leftmost element (initially $$$q$$$, $$$1$$$-indexed) and the rightmost element (initially $$$q + 1$$$). When you receive a start query, set the value at the left pointer to be the query value, and move the left pointer to the left (same on the right). For a range query, just use the segment tree based on the position of the left pointer. This is $$$O(qlogq)$$$

Their tags seem to include DP, so I'll give another solution that the setters may have intended.

(This paragraph is just me explaining prefix XORS) Let's first assume we already have a full array, and all we want are range queries. We can do this in $$$O(1)$$$ by computing prefix XORS. Let $$$pre_i$$$ be the XOR of all values $$$a_1, a_2, ..., a_i$$$. The answer to any range query on $$$l..r$$$ is $$$pre_{l-1} \oplus pre_r$$$. This is because $$$pre_r$$$ = $$$pre_{l-1} \oplus $$$ the XOR of values from $$$l$$$ to $$$r$$$ Therefore, since the XOR of values from $$$l$$$ to $$$r$$$ is exactly what we want, $$$pre_{l-1} \oplus pre_r$$$ will give us our answer because $$$a \oplus a = 0$$$. How do we compute these quickly? Simple, pass through the array once and use that $$$pre_i = pre_{i-1} \oplus a_i$$$.

Now, how do we adapt this to the problem? Fix a middle point, which all 'start' elements will go to the left of and all 'end' elements will go to the right of. Now assume no range queries will overlap this middle point (we'll get to that later). When we get an update, for either side, we just have to compute one more prefix XOR (just use the formula above). A range query is like above, just take $$$pre_{l-1} \oplus pre_r$$$. You'll have to figure out the appropriate $$$l$$$ and $$$r$$$ for each query.

We have one thing left to take care of, the case when range queries overlap the middle point. This is also quite simple, we just break the query up into its left and right side counterpart and XOR those two queries. To implement this split, just keep two lists that support append operations (like a C++ vector), being careful to process range queries on the left side backwards.

Computing a prefix XOR (for an update) is $$$O(1)$$$ and computing a range XOR is also $$$O(1)$$$, so the overall complexity is $$$O(q)$$$.

This comment is long enough, so if you want me to illustrate the $$$O(q)$$$ process with an example, just ask.