Codeforces Round #416 (Div. 2) C. Vladik and Memorable Trip
Summary:
An integer array A of size n <= 5000 has entries which ranges from 1 to 5000. We pick disjoint segments of the array such that for each segment S:
1. If i in S, then any j s.t. a[j] == a[i] must also be in S
2. The score of S is computed as the XOR of its elements
Goal is to maximise the sum of scores of the chosen segments.
Solution:
I like this problem. This is solvable using a dynamic programming approach.
Suppose dp[i] is the maximum score we can get when we are only allowed to pick segments in A[0...i]. To find dp[i], we can:
1. Skip A[i]. So dp[i] is at least as good as dp[i-1].
2. Form a segment using A[i]. To do this we need to check a few things. First, say the smallest segment we can form (satisfying the above condition) is A[j...k] (i.e. j <= i && i <= k). Now, if k > i, then we cannot use A[i] to form the current segment, as we will be using elements beyond [0..i]. If k == i, then we know that dp[i] is at least as good as dp[j-1] + score of A[j...i].
With that, the implementation is quite straightforward.
Implementation:
#include <iostream> #include <algorithm> #include <cstdio> #include <vector> #include <utility> #include <cstring> using namespace std; int main(){ int n; scanf("%d",&n); int a[5010]; vector<pair<int,int>> b; for (int i = 0; i < n; ++i) { scanf("%d",&a[i]); b.push_back({a[i], i}); } sort(b.begin(), b.end()); int r[5010][2]; int prev = b[0].second; for (int i = 1; i < n; ++i) { if (b[i].first == b[i-1].first) continue; int val = b[i-1].first; int last = b[i-1].second; r[val][0] = prev; r[val][1] = last; prev = b[i].second; } r[b.back().first][0] = prev; r[b.back().first][1] = b.back().second; int dp[5010]; int mark[5010]; for (int i = 0; i < n; ++i) { dp[i] = dp[i-1]; bool can_choose = true; int last = i; int cur = 0; memset(mark, 0, sizeof(mark)); for (int j = i; j >= last; --j) { if (r[a[j]][1] > i) { can_choose = false; break; } last = min(last, r[a[j]][0]); if (!mark[a[j]]) { cur ^= a[j]; mark[a[j]] = 1; } } if (!can_choose) continue; dp[i] = max((last - 1 >= 0 ? dp[last-1] : 0) + cur, dp[i-1]); } printf("%d\n",dp[n-1]); return 0; }
"Great explanation! I struggled to grasp the segment formation condition at first, but your breakdown made it crystal clear. Thanks!"
ReplyDeleteHeavy Duty Warehouse Racking delhiHeavy duty pallet rack delhi
"This problem highlights how dynamic programming can solve seemingly complex issues. Love the way you explained
ReplyDeleteWarehouse Pallet Racking System Delhi
two tier rack delhi
"I didn’t realize the XOR of elements could serve as a score. Very interesting approach!"
ReplyDeleteIndustrial Mezzanine Floor Delhi
cable tray delhi
"The condition where was tricky for me to understand initially, but your write-up cleared it up perfectly. Well done
ReplyDeleteSlotted Angle rack delhi
Pallet storage rack india
"One thing I found challenging was ensuring disjoint segments meet all conditions. Your insights really helped clarify that!"
ReplyDeleteIndustrial Pallet Racks india
Heavy Duty Rack
"5000-sized arrays and XOR scoring? Seems tough! Dynamic programming really is the key here."
ReplyDeleteHeavy Duty Warehouse Racking
Industrial Pallet Racks
"I appreciate the clarity in your explanation. I’ll implement the dp approach now and test it out on my own."
ReplyDeleteSpare part storage rack india
Heavy duty pallet rack noida
"Nice solution! A well-structured dynamic programming approach makes this problem much more manageable."
ReplyDeleteRacking system noida
Industrial Mezzanine Floor noida
"Thanks for sharing the intuition behind the solution. It’s always helpful to understand the reasoning rather than just the code."
ReplyDeleteMezzanine floor lucknow