- Every operation results in flipping of two elements.
- So if any subarray $$$[L, R]$$$ has
-
- Odd number of $$$+1/-1$$$, we can never make the entire subarray containing $$$+1/-1$$$ respectively.
It would be possible to convert the entire subarray to $$$-1$$$ or $$$+1$$$ if there are even occurences of it (despite odd occurences of the other value). We just need to check if the number of operations taken is $$$k$$$ or less.
Now, lets consider a subarray $$$[L, R]$$$ containing an even number of $$$-1$$$'s (lets say 4) at indices $$$p, q, r, s$$$, where $$$p \lt q \lt r \lt s$$$.
The greedy strategy for doing this would be to:
- Take adjacent pairs $$$(p, q)$$$, $$$(r, s)$$$
- For pair $$$(p, q)$$$
-
- We would perform the operation on indices $$$[p, p + 1, p + 2, ..., q - 1]$$$. $$$(q - p)$$$ Operations.
- For pair $$$(r, s)$$$
-
- We would perform the operation on indices $$$[r, r + 1, r + 2, ..., s - 1]$$$. $$$(s - r)$$$ Operations.
Now we just need to check if $$$(s - r) + (q - p) ≤ k$$$.
How do I solve this?
- Store a prefix sum for $$$+1$$$ and $$$-1$$$ occurences individually, this would help us find out their frequency in a range in $$$O(1)$$$ time. $$$O(n)$$$ processing though.
- Have two different
std::vector<int>, storing the indices of $$$+1$$$ and $$$-1$$$ occurences. Can be done in $$$O(n)$$$ aswell. - Have a $$$dp[n][2]$$$ for both of the
std::vector's.
$$$dp[i][0]$$$: total cost of operations involving indices $$$i, i + 1, ..., n - 1$$$, without considering the pair $$$(i, i + 1)$$$.
$$$dp[i][1]$$$: total cost of operations involving indices $$$i, i + 1, ..., n - 1$$$, considering the pair $$$(i, i + 1)$$$.
$$$dp[i][0]$$$ is nothing but $$$dp[i + 1][1]$$$.
$$$dp[i][1] = v[i + 1] - v[i] + dp[i + 1][0]$$$.
Base Cases:
$$$dp[n - 1][0] = 0. dp[n - 1][1] = 0;$$$
$$$dp[n - 2][0] = 0. dp[n - 2][1] = v[n - 1] - v[n - 2].$$$
Computing this also takes $$$O(n)$$$.
For a query,
- $$$O(1)$$$: Find the number of $$$+1$$$'s or $$$-1$$$'s in $$$[L, R]$$$.
- $$$O(logn)$$$: In case either of them have an even count, find the left and ritemost indices using binary search over the vectors.
- $$$O(1)$$$: prefix sum on respective $$$dp$$$ using the positions of the bounded values found in step above.
Overall compleixity is $$$O(n + qlogn)$$$.
Auto comment: topic has been updated by happywobbuffet (previous revision, new revision, compare).
Some observations:
Pretty cool observation!. I just overcomplicated it.
You can view this problem as an instance of Gaussian elimination over $$$GF(2)$$$ (in other words, XOR). First of all, change $$$1 \rightarrow 1$$$ and $$$-1 \rightarrow 0$$$. Now you have a binary string.
For example, let's say initially you have the string $$$abcd$$$. Denote an operation at the $$$i$$$-th index as $$$p_i$$$. Note that operating on an index twice does nothing. So in essence, we have the following equations if we want to make everything equal to $$$0$$$:
We can further write
Now we can eliminate to get
This means that, we need to take the prefix XOR, check that the XOR of the whole array is $$$0$$$, and then count the number of $$$1$$$-s in the prefix XOR array and check if it is $$$\leq k$$$.
This isn't the only possibility of course, you can also make everything equal to $$$1$$$. To handle that, you can just flip every bit and run the same procedure. So we'll not talk about this case, but remember to handle it (just make another array and run the procedure on both arrays and check if either one works).
So now you have an $$$O(n + q)$$$ solution to your first variant: You know how to count the number of $$$1$$$-s in the prefix XOR of a subarray $$$[L, R]$$$: maintain a prefix sum of how many $$$1$$$-s are there in the prefix XOR array, and if $$$\text{prefix_XOR}[L-1]$$$ is $$$1$$$, you have $$$R-L+1-\text{count}_1(L, R)$$$ number of $$$1$$$-s (you get the idea). Also remember to check the whole subarray XOR is $$$0$$$.
To solve your variant with type $$$2$$$ updates, I think you can see we need a Fenwick tree now.
very nice approach. took me a while to understand it!
I'm still very new to the realm of Fenwick/Segment Tree like Data Structures, could you help with some hints?
Well, a Fenwick tree can maintain and get prefix sums and prefix XORs across updates. That's all you require right? You can look up how to implement a Fenwick tree here.