[模拟] 警察的询问

文章目录


题目

题目描述

H a n Han Han找来兄弟伙 D o m i n i k Dominik Dominik帮他写程序,搞了一个通宵后, D o m i n i k Dominik Dominik有点恍惚就回家了,回家路上被警察盘问,警察怀疑他喝了酒,于是警察问:冒泡排序时间复杂度是多少? D o m i n i k Dominik Dominik轻松回答 n n n的平方。警察又问倒着说出英文字母表, D o m i n i k Dominik Dominik回答 z y x w v u t s r q p o n m l k j i h g f e d c b a zyxwvutsrqponmlkjihgfedcba zyxwvutsrqponmlkjihgfedcba。警察说这是你背的,没有思考,于是准备出道难题

现在想象一下,英语字母表中从“ a a a”到“ z z z”的所有字母都是顺时针方向写在一个圆圈里的。以字母“ a a a”开头,顺时针读。在每读一个字母后,警察会提出操作或询问,操作是以当前字母反向读,询问是当读到 n n n个字母后, x x x字母被读过几次?

明白规则后, D o m i n i k Dominik Dominik便开始从 a a a开始读了,请你编写一个程序,解决警察的问题。

输入

第一行,一个整数 Q Q Q,表示操作和询问总数 ( 1 ≤ Q ≤ 100000 ) (1 ≤ Q ≤ 100000) 1Q100000

接下来 Q Q Q行,若是 U P I T   n   x UPIT\ n\ x UPIT n x U P I T UPIT UPIT为克罗地亚语,表示询问,即读到第 n n n个字母时 x x x出现了几次?

若是 S M J E R   n SMJER\ n SMJER n S M J E R SMJER SMJER为克罗地亚语,表示操作,即读到第 n n n个字母时反向读。

x x x为小写字母 a   z a~z a z

n n n的取值范围是 ( 1 ≤ n ≤ 1 e 9 ) (1 ≤ n ≤ 1e9) (1n1e9)

输出

一共询问行

每行一个整数,询问结果,即 x x x出现的次数

样例输入

5
UPIT 1 b
UPIT 3 b
SMJER 4
UPIT 7 a
UPIT 10 z

样例输出

0
1
2
1

题解

先吐槽一波,考试时老师一直说这个题很难,搞得我想到模拟的时候一阵慌不敢打
但这个题一看就是模拟啊。。。

我们只需要用一个变量记录当前读字母的方向,由于数据保证 n n n递增,我们就直接循环两次询问之间所经过的字母,将每一个字母出现的次数加一即可,这有什么难的

最后要考虑一个优化,不然 O ( N Q ) O(NQ) O(NQ)的复杂度肯定超时,如果两次 n n n相差很大,我们可以直接算出读了多少圈,也就是每个字母一定会被读到的次数,再将剩余的处理就可以了

代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int q, n, start, step;
int cnt[30];
char s;
char a[10];
bool dir;	//0顺1逆

int main() {
	scanf("%d", &q);
	step = 0;
	start = 0;
	for(int i = 1; i <= q; i ++) {
		scanf("\n");
		scanf("%s", a);
		scanf("%d", &n);
		int p = n - step;
		for(int i = 1; i <= 26; i ++)
			cnt[i] += p / 26;
		p %= 26;
		if(dir == 0) {
			for(int i = 1; i <= p; i ++) {
				if(start + i <= 26) cnt[start + i] ++;
				else cnt[(start + i) % 26] ++;
			}
			start += p;
			if(start > 26) start %= 26;
		}
		else {
			for(int i = 1; i <= p; i ++) {
				if(start - i >= 1) cnt[start - i] ++;
				else cnt[start - i + 26] ++;
			}
			start -= p;
			if(start < 1) start += 26;
		}
		if(a[0] == 'U') {
			s = getchar();
			s = getchar();
			printf("%d\n", cnt[s - 'a' + 1]);
		}
		else {
			if(dir == 0) dir = 1;
			else dir = 0;
		}
		step = n;
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值