Parallel Handshakes
Autumn Tournament (2009)
Submission name: handshakes.cpp
Problem summary
People stand in a row facing left (L) or right (R). Each second, every adjacent RL pair shakes hands and both people turn, changing RL into LR simultaneously. Find the number of seconds until no handshake is possible and the total number of handshakes.
Input
One nonempty string of L and R characters.
Output
Time and total handshakes, separated by a space. The source also names NEVEREND for an infinite process; this cannot occur for a finite valid row.
Constraints
String length is at most 100000.
Worked example
Original statement sample.
Input
RLLRLRR
Output
3 4
Solution analysis
- Think of a right-facing person as a token moving right across left-facing people. Every R before an L forms one inversion, and they eventually shake hands exactly once. While scanning, count previous R characters; each L contributes that count to the total.
- For the time, maintain seconds for the processed prefix. An L with r previous R characters needs at least r seconds to cross them. If earlier left-facing people are already moving, it may also need one second after their completion. Therefore update seconds=max(seconds+1,r) when r>0.
- For RLLRLRR, the first two L characters have one R before them, contributing 1+1 handshakes and finishing after seconds 1 and 2. The third L has two R characters before it, contributes 2 more, and finishes at max(3,2)=3. Hence output 3 4.
Why it works
Each RL→LR exchange removes exactly one inversion and creates none, so infinitely many rounds are impossible. A left-facing token must wait for its preceding right-facing tokens and for the token ahead of it; these give the two terms in the completion-time recurrence. Once these constraints are met, every adjacent pair acts immediately, so the bound is attained.
Watch out. Do not update the string in place to simulate a simultaneous second: doing so can move a person multiple times. If there is no earlier R, an L creates no delay. Use 64-bit inversion totals.
Commented C++17 solution
An independently written complete program with standard headers.
#include<algorithm>
#include<iostream>
#include<string>
using namespace std;
int main(){
string row;
cin>>row;
long long rightCount=0;
long long handshakes=0;
long long seconds=0;
for(char facing:row){
if(facing=='R'){
rightCount++;
}
else if(rightCount>0){
handshakes+=rightCount;
// Account for both crossings and the token immediately ahead.
seconds=max(seconds+1,rightCount);
}
}
cout<<seconds<<' '<<handshakes<<'\n';
}