/*
Problem: Final Black Positions After Executing Prefix Commands
Company Tag: GrowthJockey
Problem Statement:
We have task positions from 1 to 10^9.
Some positions are initially black.
All other positions are white.
We are given a command string s.
For every prefix of s, a new worker starts at position 1.
Commands:
A -> move from x to x + 1
B -> move from x to the nearest white position strictly greater than x
After each worker finishes, the final position becomes black.
We need to print all black positions at the end.
Constraints:
1 <= n, m <= 2 * 10^5
1 <= initialBlack[i] <= 10^9
s contains only characters 'A' and 'B'
The task range is too large to use a direct array.
Simple Brute Force:
For each prefix, simulate the whole prefix from position 1.
Why Brute Force Fails:
There are O(n) prefixes.
Simulating every prefix from scratch can take O(n^2).
Better Idea:
Use a DSU-like next pointer to quickly find the next white position.
findWhite(x) gives the smallest white position >= x.
When a position becomes black:
we link it to the next white position.
This lets us skip already black positions efficiently.
Dry Run:
s = "ABAA"
initially black = {2}
Worker 1:
A -> 2
black = {2}
Worker 2:
A -> 2
B -> 3
black = {2, 3}
Worker 3:
A -> 2
B -> 4
A -> 5
black = {2, 3, 5}
Worker 4:
Final position becomes 6
Final black positions:
2 3 5 6
Time Complexity:
O((n + m) log(n + m))
Space Complexity:
O(n + m)
*/
#include <bits/stdc++.h>
using namespace std;
class NextWhiteFinder {
public:
unordered_map<long long, long long> parent;
long long findWhite(long long x) {
vector<long long> path;
// Keep jumping while x is already black.
while (parent.find(x) != parent.end()) {
path.push_back(x);
x = parent[x];
}
// Compress the path so future searches become faster.
for (long long node : path) {
parent[node] = x;
}
return x;
}
void markBlack(long long x) {
// Once x becomes black, the next possible white position starts from x + 1.
parent[x] = findWhite(x + 1);
}
};
int main() {
int n, m;
cin >> n >> m;
string s;
cin >> s;
NextWhiteFinder dsu;
set<long long> black;
for (int i = 0; i < m; i++) {
long long x;
cin >> x;
black.insert(x);
dsu.markBlack(x);
}
long long previousFinal = 1;
for (int i = 0; i < n; i++) {
long long currentPosition;
if (i == 0) {
currentPosition = 1;
} else {
currentPosition = previousFinal;
/*
If the previous command was B, then the previous final position
was found as a white position and then marked black.
So now we need to move to the next white position.
*/
if (s[i - 1] == 'B') {
currentPosition = dsu.findWhite(currentPosition + 1);
}
}
if (s[i] == 'A') {
currentPosition++;
} else {
currentPosition = dsu.findWhite(currentPosition + 1);
}
// Add the final position of this worker to the black set.
if (black.insert(currentPosition).second) {
dsu.markBlack(currentPosition);
}
previousFinal = currentPosition;
}
cout << black.size() << endl;
for (long long x : black) {
cout << x << " ";
}
cout << endl;
return 0;
}