题意
从每个顶点出发,求它最多能经过的顶点数。每走一个顶点,有向边的方向会调换,因此可以得出走过去必定能走回来。因此答案==左边顶点数+右边顶点数,即右边顶点最远-左边顶点最远+1.
想到这里就很容易想到用dp做,有三种情况,以右为例。
- 往右不能走,
r[i]=i
。 - 往右能走一步,
r[i]=i+1
。因为走一步方向会变相反,所以需要考虑这种情况。 - 往右走两步,
r[i]=r[i+2]
。因为走两步方向又回来了,可以递推求解。
边界两种:
- i==n,i 已经是最右了,即
r[i]=i
。 - i==n-1,往右最多走一次,判断能不能往右,能
r[i]=i+1
,不能r[i]=i
。
代码
#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
using namespace std;
typedef long long ll;
typedef long double ld;
const int maxn=3e5+5;
int l[maxn],r[maxn];
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int t;
cin>>t;
while(t--){
int n;
string s;
cin>>n>>s;
for(int i=0;i<=n;i++){
if(i==0 || s[i-1]=='R'){
l[i]=i;
}else if(i==1 || s[i-2]=='L'){
l[i]=i-1;
}else{
l[i]=l[i-2];
}
}
for(int i=n;i>=0;i--){
if(i==n || s[i]=='L'){
r[i]=i;
}else if(i==n-1 || s[i+1]=='R'){
r[i]=i+1;
}else{
r[i]=r[i+2];
}
}
for(int i=0;i<n;i++){
cout<<r[i]-l[i]+1<<" ";
}
cout<<r[n]-l[n]+1<<endl;
}
return 0;
}