[Cqoi2015] 编号 [思维题,模拟]

时间:2019-09-08
本文章向大家介绍[Cqoi2015] 编号 [思维题,模拟],主要包括[Cqoi2015] 编号 [思维题,模拟]使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Online Judge牛客网NOIP2018赛前集训营-提高组(第八场)T1

Label:思维题,模拟

ps:这套题目由于被改成模拟离线赛,所以下面的题目描述改编了,题目还是一样的。


题目描述

众所周知,Sheldon是一个领地意识极强的人。

最近Leonard和Sheldon一起买了一张新沙发,这个沙发很长,上面一共有nn个坐垫,也就是说只有nn个位置,而且每个位置上只能做一个人。在Sheldon在慎重挑选后,他找了一个位置,并向Leonard提出要长期占有这个位置。

终于,Leonard无法再忍受Sheldon对沙发座位的无理要求,要和Sheldon争夺沙发座位!!

Leonard会挑选若干个连续的位置(可以是零个)并占领它们。Sheldon当然不会示弱,他也像Sheldon一样挑选若干个连续的位置(可以是零个)并占领它们。这时Leonard也不乐意了,于是又占领了一些位置。Sheldon又不高兴了。。。。。。

最后两人都累了,由于刚才过于激动,所以忘记了自己曾经占领过什么位置,只记得自己最后占领了什么位置(一个位置可能在被Leonard占领后又被Sheldon气愤的占领,而且任何时候一个位置都只能被至多一个人占领)。很巧的是,所有的位置最后都被占领了。由于中途Leonard和Sheldon可能会去上厕所,所以两人并不是交替占领位置的,而可能有人会连续两次占位置。

在一旁的Penny却默默记住了两个人占领的时间顺序,由于Penny对自己的记忆力有所怀疑,所以找来了老X来确定一下自己所记下的顺序是否是对的。简单地说就是让老X确定一下是否存在某种占领方案使得占领到最后跟Leonard与Sheldon的“领地”符合。

输入

第一行包含一个整数T,表示本组数据共有T组测试点。

对每组测试点的第一行是一个由RB组成的字符串s表示最终格子的颜色。R表示Sheldon的领地,B表示Leonard的领地,同时字符串的长度为n。

第二行是一个由FL组成的字符串t表示m次操作,F表示某次是Sheldon操作,L表示是Leonard操作,同时字符串的长度为m。

输出

对每组测试点输出一行,如果满足条件输出Yes否则输出No。

样例

Input

3
R
FL
RRRBR
FFFF
BRRBBRB
LFL

Output

Yes
No
Yes

Hint

100%的数据满足\(n,m≤100000\)

所有数据满足\(T≤20\)

题解

正着按时间轴来模拟情况会很复杂,尝试看样例找规律也没什么发现,不太可做。

但是发现,最后留下的颜色一定是那一段的最后一笔(废话)。我们尝试倒序逆着时间轴模拟操作,相应的,填涂颜色变成消除颜色,为什么这两者等价呢。看下面的例子:

逆序时:在第t秒,我们删除中间这一段R

第t秒:\([][][][]BBBRRBBB[][][]\)

第t-1秒:\([][][][]BBB[][]BBB[][][]\)

正序时:在第t-1秒,我们将一段R覆盖在B

第t-1秒:\([][][][]BBBBBBBB[][][]\)

第t秒:\([][][][]BBBRRBBB[][][]\)

相比之下,第t-1秒的情况,只是逆序去做时:中间空了一段,正序做时:中间是连接着的。但是两者其实没有差别。因为逆序操作时,中间那一段不可能再被填上颜色,所以我们可以将两端的B合并了,而这也就相当于正序时的那一段。

做法就出来了,只要模拟这个过程就好了。当然模拟并不需要真的用双向链表之类的东西去维护,我们一开始记录一个\(cntb,cntr\)即可,表示初始时L的块数R的块数。然后从后往前根据题目给的操作序列来消除一整块。

注意一点,最后判的时候是\(cntb<=0\)&&\(cntr<=0\),取≤是因为中间操作时可以选择不涂色。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int main(){
    int T;scanf("%d",&T);
    while(T--){
        char a[N],op[N];
        scanf("%s",a+1);scanf("%s",op+1);
        int len=strlen(a+1),round=strlen(op+1);
        int cntr=0,cntb=0;
        for(int i=1;i<=len;i++)if(a[i]!=a[i-1]){
            if(a[i]=='R')cntr++;
            else cntb++;
        }
        for(int i=round;i>=1;i--){
            if(op[i]=='L'){
                cntb--;if(cntr>=2)cntr--;
            }
            else{
                cntr--;if(cntb>=2)cntb--;
            }
        }
        if(cntb<=0&&cntr<=0)puts("Yes");
        else puts("No");
    }
}

原文地址:https://www.cnblogs.com/Tieechal/p/11487846.html