题目描述

$Cab$有两行石子,每个石子上有一个字母,为$'C''A''B'$中的一个。
一开始,在每行第一个石子上站着一只$lucky$,$Cab$每次可以选择一个字母,使得所站石子上字母为该字母的$lucky$向前走一步,如果此时$lucky$已经到了一行石子的结尾就会掉出去,$Cab$显然不会这么做。
一个数对$(x,y)$是$lucky$的,当且仅当在$lucky$不掉出去的前提下,通过一些操作能使第一行的$lucky$处于第$x$个石子的同时第二只$lucky$处于第$y$个石子。
请求出有多少个$lucky$的数对。


输入格式

第一行一个长度为$n$的字符串表示第一行石子。
第二行一个长度为$m$的字符串表示第二行石子。


输出格式

输出一个答案表示$lucky$的数对个数。


样例

样例输入:

CAB
ABCAB

样例输出:

11


数据范围与提示

对于$30\%$的数据:$n\leqslant 1,000,m\leqslant 1,000$。
对于另$30\%$的数据:$n\leqslant 50,000,m\leqslant 50,000$,且两个字符串中只含有两种字母。
对于$100\%$的数据:$n\leqslant 1,000,000,m\leqslant 1,000,000$。


题解

官方题解画了一堆图,我也没看懂。

对于第一个串中的每一个点,其有一个覆盖范围$(l,r)$,可以用贪心的思想,$l$即为尽可能让其不动;$r$则为尽可能让它动;注意边界即可。

但是打个表会发现,这中间有一些点还是不能取到;再认真看一下,会发现对于当前点$a_i$,如果$a_i=b_j$且$a_{i-1}=b_{j+1}$,那么这个$(i,j)$是不可取的。

那么答案就是:

$$ans=\sum \limits_{i=1}^n r_i-l_i+1-num[i]$$

上式中的$num[i]$即为$l_i\sim r_i$中$a_i=b_j$且$a_{i-1}=b_{j+1}$的个数。

$num$数组可以用桶$+$前缀和$+$差分处理。

如果你发现$WA90$的话可以考虑将两个串的读入顺序交换即可。

时间复杂度:$\Theta(n+m)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int a[1000001],b[1000001],la,lb;
char ch1[1000001],ch2[1000001];
int l[1000001],r[1000001];
int t[1000001][6];
long long ans;
int main()
{
scanf("%s%s",ch1+1,ch2+1);
la=strlen(ch2+1);
lb=strlen(ch1+1);
for(int i=1;i<=la;i++)
a[i]=ch2[i]-'A'+1;
for(int i=1;i<=lb;i++)
b[i]=ch1[i]-'A'+1;
int faill=1,failr=1;
for(int i=1;i<=la;i++)
{
while(a[i]!=b[failr]&&failr<lb)failr++;
l[i]=faill;r[i]=failr;
if(a[i]==b[faill]&&faill<lb)faill++;
if(failr<lb)failr++;
}
for(int i=2;i<=lb;i++)
{
if(b[i-1]==1&&b[i]==2)t[i][0]++;
if(b[i-1]==2&&b[i]==1)t[i][1]++;
if(b[i-1]==1&&b[i]==3)t[i][2]++;
if(b[i-1]==3&&b[i]==1)t[i][3]++;
if(b[i-1]==2&&b[i]==3)t[i][4]++;
if(b[i-1]==3&&b[i]==2)t[i][5]++;
t[i][0]+=t[i-1][0];
t[i][1]+=t[i-1][1];
t[i][2]+=t[i-1][2];
t[i][3]+=t[i-1][3];
t[i][4]+=t[i-1][4];
t[i][5]+=t[i-1][5];
}
ans=r[1]-l[1]+1;
for(int i=2;i<=la;i++)
{
ans+=r[i]-l[i]+1;
if(a[i]==a[i-1])continue;
if(a[i]==1&&a[i-1]==2)ans-=t[r[i]][0]-t[l[i]-1][0];
if(a[i]==2&&a[i-1]==1)ans-=t[r[i]][1]-t[l[i]-1][1];
if(a[i]==1&&a[i-1]==3)ans-=t[r[i]][2]-t[l[i]-1][2];
if(a[i]==3&&a[i-1]==1)ans-=t[r[i]][3]-t[l[i]-1][3];
if(a[i]==2&&a[i-1]==3)ans-=t[r[i]][4]-t[l[i]-1][4];
if(a[i]==3&&a[i-1]==2)ans-=t[r[i]][5]-t[l[i]-1][5];
}
printf("%lld",ans);
return 0;
}

rp++

[CSP-S模拟测试]:stone(结论+桶+前缀和+差分)的更多相关文章

  1. 第 45 届国际大学生程序设计竞赛(ICPC)亚洲网上区域赛模拟赛. A.Easy Equation (前缀和/差分)

    题意:RT,给你四个数\(a,b,c,d\),求\(x+y+z=k\)的方案数. 题解:我们可以先枚举\(x\)的值,然后\(x+y\)能取到的范围一定是\([x,x+b]\),也就是说这个区间内每个 ...

  2. [CSP-S模拟测试]:电压机制(图论+树上差分)

    题目描述 科学家在“无限神机”($Infinity\ Machine$)找到一个奇怪的机制,这个机制有$N$个元件,有$M$条电线连接这些元件,所有元件都是连通的.两个元件之间可能有多条电线连接.科学 ...

  3. 2019.8.1 NOIP模拟测试11 反思总结

    延迟了一天来补一个反思总结 急匆匆赶回来考试,我们这边大家的状态都稍微有一点差,不过最后的成绩总体来看好像还不错XD 其实这次拿分的大都是暴力[?],除了某些专注于某道题的人以及远程爆踩我们的某学车神 ...

  4. Mockito:一个强大的用于Java开发的模拟测试框架

    https://blog.csdn.net/zhoudaxia/article/details/33056093 介绍 本文将介绍模拟测试框架Mockito的一些基础概念, 介绍该框架的优点,讲解应用 ...

  5. Mock 模拟测试简介及 Mockito 使用入门

    Mock 是什么mock 测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法.这个虚拟的对象就是mock对象.mock对象就是真实对象在调试期间的代 ...

  6. noi2019模拟测试赛(四十七)

    noi2019模拟测试赛(四十七) T1与运算(and) 题意: ​ 给你一个序列\(a_i\),定义\(f_i=a_1\&a_2\&\cdots\&a_i\),求这个序列的所 ...

  7. csp-s模拟测试93

    csp-s模拟测试93 自闭场. $T1$想到$CDQ$,因为复杂度少看见一个$0$打了半年还用了$sort$直接废掉,$T2$,$T3$直接自闭暴力分都没有.考场太慌了,心态不好. 02:07:34 ...

  8. csp-s模拟测试91

    csp-s模拟测试91 倒悬吃屎的一套题. $T1$认真(?)分析题意发现复杂度不能带$n$(?),计划直接维护答案,考虑操作对答案的影响,未果.突然发现可以动态开点权值线段树打部分分,后来$Tm$一 ...

  9. csp-s模拟测试89

    csp-s模拟测试89 $T1$想了一会儿没什么思路,一看$T2$  $1e18$当场自闭打完暴力就弃了,$T3$看完题感觉要求$lca$和$dep$,手玩了一下样例发现$lca$很显然,$dep$貌 ...

随机推荐

  1. keil格式化项目代码

    有时候需要用到一个功能,就先会在网上找到对应的程序,但是百度直接拿来的程序通常不是很规范.想着keil5要是有一个自动格式化代码的功能就好啦,上网一查还真有!需要一些设置如下(keil4与keil5都 ...

  2. [.net core]6.launchSettings.json,调试配置

    展开properties, 双击查看内容, { "iisSettings": { "windowsAuthentication": false, "a ...

  3. JAVA重写不需要@override

    一,如下代码, package com.boot.enable.bootenable; import org.springframework.scheduling.annotation.Async; ...

  4. oracle链接报错shared memory realm does not exist

    问题描述: 前两天能够正常链接,今天来了突然不能链接,原因不详. 处理方法: 连接linux进行如下操作: 1.sqlplus /nolog 2.conn / as sysdba 3.startup ...

  5. 集合类Hash Set,LinkedHashSet,TreeSet

    集合(set)是一个用于存储和处理无重复元素的高效数据结构.映射表(map)类似于目录,提供了使用键值快速查询和获取值的功能. HashSet类是一个实现了Set接口的具体类,可以使用它的无参构造方法 ...

  6. java 统计字符串中连续重复的字符,并得出新字符串

    题目: 比如输入为aaabbc,输出a3b2c1 完整解答: public class Other { static String func(String str) { StringBuffer re ...

  7. Linux部署Redis及PHP-redis扩展

    Redis是一个key-value存储系统,属于我们常说的NoSQL.它遵守BSD协议.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.它常用在缓存.队列.P ...

  8. fdisk磁盘挂载

    1.查看磁盘信息 fdisk –l 2.分区 fdisk /dev/vdb :h 帮助命令 :p 查看 :n 进行分区 e  extended  逻辑分区 p  primary partition ( ...

  9. 004-SaltStack入门篇之数据系统Grains、Pillar

    1.什么是Grains? Grains是saltstack的组件,用于收集salt-minion在启动时候的信息,又称为静态信息.可以理解为Grains记录着每台Minion的一些常用属性,比如CPU ...

  10. 数据结构之查找(图片来源,老师PPT)

    顺序查找进行遍历元素,进行查找 总计全部比较次数为:1+2+…+n = (1+n)n/2 若求某一个元素的平均查找次数,还应当除以n(等概率), 即: ASL=(1+n)/2 ,时间效率为 O(n) ...