2021-2022-1 ACM集训队每周程序设计竞赛 - 问题 D: 喜剧表演- 题解

Posted Tisfy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-2022-1 ACM集训队每周程序设计竞赛 - 问题 D: 喜剧表演- 题解相关的知识,希望对你有一定的参考价值。


喜剧表演

时间限制:1秒
空间限制:256M


题目描述

剧院里正上演着一部喜剧,喜剧中共有一排 N N N个大盘子,每个盘子上标有一个字符LR

喜剧刚开始时,每个盘子中有一只小丑🤡。这些不只疲倦的小丑啊,在盘子之间跳来跳去

如果某只小丑所在的盘子标的是L,那么它下一步将会往左跳。
如果某只小丑所在的盘子标的是R,那么它下一步将会往右跳。

当每只小丑都跳了 1 0 100 10^100 10100次时,喜剧结束

那么请问喜剧结束时,每只盘子中分别有几只小丑呢?


输入描述

输入包括 1 1 1行一个字符串,字符串的长度为 N N N
字符串由 L L L R R R组成,代表了 N N N个大盘子上的标号。

数据范围

  • 1 ≤ N ≤ 1 0 5 1\\leq N\\leq 10^5 1N105
  • S S S的第一个字符是 R R R(最左边的盘子上标记的字母一定是 R R R)
  • S S S的最后一个字符是 L L L(最右边的盘子上标记的字母一定是 L L L,也就是说小丑不会跳出这 N N N个盘子)

输出描述

输出一行空格隔开的 N N N个数,代表每只小丑都跳 1 0 100 10^100 10100次后,每只盘子中的小丑数量

例如初始时有 5 5 5个盘子,从左到右的标记依次是 R R L R L RRLRL RRLRL

  • 初始状态 5 5 5个盘子上的小丑数量分别为: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
  • 每只小丑都跳一次后: 0 0 0 2 2 2 1 1 1 1 1 1 1 1 1
  • 每只小丑都跳两次后: 0 0 0 1 1 1 2 2 2 1 1 1 1 1 1
  • 每只小丑都跳 1 0 100 10^100 10100次后: 0 0 0 1 1 1 2 2 2 1 1 1 1 1 1

样例一

输入

RRLRL

输出

0 1 2 1 1

题目分析

每只小丑都要跳 1 0 100 10^100 10100次,这个次数远远大于盘子的数量。因此最终每只小丑都会在相邻的两个 L L L R R R之间反复横跳。

假设有两个相邻的 L R LR LR,初始时在 L L L上的那个小丑,第一次跳到 R R R上,第二次跳到 L L L上, ⋯ \\cdots 。奇数次跳到 L L L上,偶数次后跳到 R R R上。那么 1 0 100 10^100 10100次就会跳回左边的 L L L上。

接下来我们往左拓展一个盘子,假如 L R LR LR左边还是 L L L(即 L L R LLR LLR)。那么最左边的那个小丑就需要比第二个小丑多一步才能到达第二个小丑原来的位置,之后就会像第二个小丑一样在 L R LR LR之间反复横跳。但奇数次跳跃后会到 L L L上,偶数次跳跃后会跳到 R R R上。

同理,对于一段连续的 L L ⋯ L R LL\\cdots LR LLLR,假设有 l L lL lL L L L,那么经过居多的偶数次跳跃后,就会有 ⌊ l L / 2 ⌋ \\lfloor lL/2\\rfloor lL/2个小丑位于 R R R上, l L − ⌊ l L / 2 ⌋ lL-\\lfloor lL/2\\rfloor lLlL/2个小丑位于 R R R左边的 L L L上。

同理,对于一段连续的 L R R ⋯ R LRR\\cdots R LRRR( l R lR lR个连续的 R R R),经过居多偶数次跳跃后,有 ⌊ l R / 2 ⌋ \\lfloor lR/2\\rfloor lR/2个小丑位于 R R R左边的 L L L上, l L − ⌊ l R / 2 ⌋ lL-\\lfloor lR/2\\rfloor lLlR/2个小丑位于 L L L右边的 R R R上。

因此,我们只需要把原始字符串分割成数个 L L ⋯ L R R ⋯ R LL\\cdots LRR\\cdots R LLLRRR
计算出有 l L lL lL L L L l R lR lR R R R,那么就能统计到最终分别由多少小丑位于相邻的 L R LR LR上。


AC代码

#include <bits/stdc++.h>
using namespace std;
int ans[100010] = 0; // 最终答案
int main() 
    string s;
    cin >> s;
    s += 'R'; // 原串末尾一定是L,因此加上一个R,遍历到R时,就会计算前一段连续的L对答案所产生的贡献
    char last = s[0]; // 上一个字符L还是R
    int lastLoc = 0; // 上次统计到的下标LastLocation
    for (int i = 1; i < s.size(); i++)  // 从第二个开始遍历
        if (s[i] != s[i - 1])  // 这个和上一个不同,看是一些R遇到了L还是一些L遇到了R
            if (s[i] == 'L')  // [lastLoc, i)都是R0
                int lR = i - lastLoc; // R的个数
                int halfLR = lR / 2; // 一半向下取整
                ans[i] += halfLR; // L右边的R上增加halfLR
                ans[i - 1] += lR - halfLR; // R右边的L上增加lR-halfLR
            
            else  // [lastLoc, i)都是L
                int lL = i - lastLoc; // 与上同理
                int halfLL = lL / 2;
                ans[lastLoc - 1] += halfLL;
                ans[lastLoc] += lL - halfLL;
            
            lastLoc = i; // 更新lastLoc
            last = s[i]; // 和last
        
    
    for (int i = 0; i < s.size() - 1; i++)  // 因为原串增加了一个字符,因此输出从0到s.size()-1
        printf("%d ", ans[i]);
    
    puts(""); // 换行
    return 0;

原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/121551485

以上是关于2021-2022-1 ACM集训队每周程序设计竞赛 - 问题 D: 喜剧表演- 题解的主要内容,如果未能解决你的问题,请参考以下文章

BUCT - 2021-2022-1 ACM集训队每周程序设计竞赛(10)题解

BUCT - 2021-2022-1 ACM集训队每周程序设计竞赛题解

BUCT - 2021-2022-1 ACM集训队每周程序设计竞赛题解

BUCT - 2021-2022-1 ACM集训队每周程序设计竞赛题解

2021-2022-1 ACM集训队每周程序设计竞赛题解

2021-2022-1 ACM集训队每周程序设计竞赛题解