Algorithmic Analysis & Solution
Topic: Simulation, Suffix Sums, Ad-hoc
Brute Force?
Iterate every command $i$, change it to the other 2 types, and re-simulate.
Complexity: $O(C^2)$. With $C \le 10^5$, this will Time Out (TLE).
Optimized Approach ($O(C)$):
Key Observation: Global Shift.
Changing a move creates a constant offset for the entire future path.
Example: Changing $L$ (-1) to $R$ (+1) increases the position by 2 for all future steps.
We need to pre-calculate how many targets the suffix hits under 5 distinct shifts.
| Original | New | Pos Change | Global Offset | Map Index |
|---|---|---|---|---|
| R (+1) | L (-1) | $-2$ | Left 2 | 0 |
| R (+1) / F (0) | F (0) / L (-1) | $-1$ | Left 1 | 1 |
| Any | Same | $0$ | No Change | 2 |
| L (-1) / F (0) | F (0) / R (+1) | $+1$ | Right 1 | 3 |
| L (-1) | R (+1) | $+2$ | Right 2 | 4 |
1. Offline Pre-calculation (Suffix):
We use 5 Maps to simulate the future:
map<int, int> right[5]2. Simulation Scan (Prefix):
set<int> left: Unique targets hit before current index.left.size() + right[shift_index].size().To count distinct targets, we must avoid double counting between the Prefix (left) and Suffix (right).
// If current command is 'F' and it hits a target P
if (targets.count(p) && left[p] == 0) {
// 1. Claim it for the "Left" (past) set
left[p]++;
// 2. Remove it from ALL "Right" (future) maps
// Since we hit it now, future hits on this target add no value
for (int j = 0; j < 5; j++) right[j].erase(p);
}
Greedy Removal: Once a target is claimed by the prefix, we erase it from the suffix maps entirely. This ensures left.size() + right.size() is always accurate.
#include <bits/stdc++.h>
using namespace std;
int t, c;
char s[100005];
set<int> targets;
// left: Targets hit in the past (Prefix)
map<int,int> left_hits;
// right[5]: Targets hit in the future (Suffix) under offsets -2 to +2
// Indexes: 0:(-2), 1:(-1), 2:(0), 3:(+1), 4:(+2)
map<int,int> right_hits[5];
int ans;
int main() {
scanf("%d %d", &t, &c);
for (int i = 0; i < t; i++) {
int p; scanf("%d", &p); targets.insert(p);
}
scanf("%s", s);
int p = 0;
// --- Step 1: Pre-calculate Suffixes ---
for (int i = 0; i < c; i++) {
if (s[i] == 'L') p--;
if (s[i] == 'R') p++;
if (s[i] == 'F') {
// Record hits for all possible future offsets
if (targets.count(p-2)) right_hits[0][p-2]++;
if (targets.count(p-1)) right_hits[1][p-1]++;
if (targets.count(p)) right_hits[2][p]++;
if (targets.count(p+1)) right_hits[3][p+1]++;
if (targets.count(p+2)) right_hits[4][p+2]++;
}
}
// --- Step 2: Simulate Prefix & Try Changes ---
p = 0;
for (int i = 0; i < c; i++) {
int current_score = left_hits.size();
// Check if changing to F hits a *new* target right now
int hit_if_change_to_F = (left_hits.count(p) == 0 && targets.count(p)) ? 1 : 0;
if (s[i] == 'L') {
// Option A: Change L -> F (Global Shift +1)
// Note: If right_hits has p, we rely on the map size.
if (right_hits[3].count(p))
ans = max(ans, current_score + (int)right_hits[3].size());
else
ans = max(ans, current_score + hit_if_change_to_F + (int)right_hits[3].size());
// Option B: Change L -> R (Global Shift +2)
ans = max(ans, current_score + (int)right_hits[4].size());
p--; // Execute actual move L
}
else if (s[i] == 'R') {
// Option A: Change R -> F (Global Shift -1)
if (right_hits[1].count(p))
ans = max(ans, current_score + (int)right_hits[1].size());
else
ans = max(ans, current_score + hit_if_change_to_F + (int)right_hits[1].size());
// Option B: Change R -> L (Global Shift -2)
ans = max(ans, current_score + (int)right_hits[0].size());
p++; // Execute actual move R
}
else { // s[i] == 'F'
// We are passing this 'F', so remove its contribution from the FUTURE maps
// Decrement counts; erase if count reaches 0
for (int j = 0; j < 5; j++)
if (right_hits[j].count(p+j-2)) {
if (--right_hits[j][p+j-2] == 0) right_hits[j].erase(p+j-2);
}
// Try changing F -> L (Shift -1) or F -> R (Shift +1)
ans = max(ans, current_score + (int)right_hits[1].size());
ans = max(ans, current_score + (int)right_hits[3].size());
// Execute actual F: Claim target if valid
if (targets.count(p) && left_hits.count(p) == 0) {
left_hits[p]++;
// Crucial: Remove claimed target from ALL future maps
for (int j = 0; j < 5; j++) right_hits[j].erase(p);
}
}
}
// Finally, consider making NO changes
ans = max(ans, (int)left_hits.size());
printf("%d\n", ans);
return 0;
}