题意

从0号点到n号点排列在直线上。
n条有向边连接着这些点。
L表示向左,R表示向右。
对于每一个点,求它起点最多可达多少个点。

思路

  • 首先考虑LRLR相间的情况:
    在这样的子段上,奇数点(从0开始算)可达子段所有点,偶数点所有点都不可达
  • 然后考虑RRRR/LLLL的情况:
    在这样的子段上,每个点都只能到达自己和旁边的一个点,共2个点
    所有的段都是由这两种情况组成的
  • 考虑接壤LLR的情况:
    0L1R2R3
    1 3 2 1
    接壤情况不存在相互影响

综合来看,只需要考虑每个点左边是不是L 右边是不是R即可
如果左边是L,或右边是R,就看顺着方向,看交叉的路能走到多远

Solution

#include <bits/stdc++.h>
#define sc(x) scanf("%d", &(x))
#define pr(x) printf("%d\n", (x))
#define rep(i, l, r) for (int i = (l); i <= (r); ++i)
using namespace std;
typedef long long ll;
const int N = 1e5 + 7;
const int mod = 1e9 + 7;
int main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int T, n;
    cin >> T;
    string s;
    while (T--) {
        cin >> n >> s;
        vector<int> L(n), R(n); // 左右延伸距离
        L[0] = 1;
        for (int i = 1; i < n; i++) {
            if (s[i] == s[i - 1])
                L[i] = 1;
            else
                L[i] = L[i - 1] + 1;
        }
        R[n - 1] = 1;
        for (int i = n - 2; i >= 0; i--) {
            if (s[i] == s[i + 1])
                R[i] = 1;
            else
                R[i] = R[i + 1] + 1;
        }
        for (int i = 0; i <= n; i++) {
            int ans = 1;
            if (i) ans += s[i - 1] == 'L' ? L[i - 1] : 0;
            if (i != n) ans += s[i] == 'R' ? R[i] : 0;
            cout << ans << ' ';
        }
        cout << '\n';
    }
    return 0;
}

/*
0 1 2 3
 l r l
 r l r
*/