牛客周赛 round2

目录

1.小红的环形字符串

2.相邻不同数字的标记

3.小红的俄罗斯方块

4.小红打怪


1.小红的环形字符串

题目描述

小红拿到了一个环形字符串s。所谓环形字符串,指首尾相接的字符串。
小红想顺时针截取其中一段连续子串正好等于t,一共有多少种截法?

输入描述:

第一行输入字符串 s。
第二行输入字符串 t。
1≤len(t)≤len(s)≤1000

输出描述:

环形字符串 s 截取一段连续子串等于字符串 t 的方案数。

示例1

输入

ababab
aba

输出

3

说明

 

由于首尾相连,所以有3种截法,如下图:

思路

定义一个字符串为原字符串遍历两次,例如输入abc,定义一个字符串为abcabc,利用string的substr方法

代码

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
	string ss, t, s;
	int ans = 0;
	cin >> ss >> t;
	s = ss + ss;
	int len = ss.length();
	int lent = t.length();
	for (int i = 0; i < len; i++) {
		if (s.substr(i, lent) == t) {
			ans++;
		}
	}
	cout << ans << endl;
	return 0;
}

2.相邻不同数字的标记

题目描述

小红拿到了一个数组,每个数字被染成了红色或蓝色。

小红有很多次操作,每次操作可以选择两个相邻的不同颜色的数字标记,并获得它们数字之和的得分。已经被标记的数字无法再次标记。
小红想知道,自己最多能获得多少分。

输入描述:

第一行输入一个正整数 n ,代表数组的长度。
第二行输入 n 个正整数 ai​,代表小红拿到的数组。

第三行输入一个仅包含 'R' 和 'B' 的字符串,第 iii 个字符为 'R' 代表数组第 i 个数被染成红色,'B'代表被染成蓝色。

1≤n≤10^5

1≤ai≤10^9

输出描述:

输出一个整数,表示小红最多能获得的分值。

示例1

输入

5
1 3 2 6 5
BRRBB

输出

12

说明

第一次选择标记第一个数和第二个数,标记的数是1和3。
第二次选择标记第三个数和第四个数,标记的数是2和6。
总得分为1+3+2+6=12

思路

这是一道经典的dp问题,当前的选择会影响下一步的选择(比如字符串RBR,B与两个R均相邻,但选择第一个R后无法选择第二个R,) 考虑用动态规划

dp[i]表示1~i个数字所得到的最大分数,每次判断时先继承dp[i-1],在i和i-1颜色不同时

①不选 i, dp [ i ] = dp [ i - 1 ]

②选i , dp [ i ] = dp [ i - 2 ] + a [ i ] + a [ i - 1]

取两者中大的

dp[i] = max(dp[i - 1], dp[i - 2] + a[i] + a[i - 1]);

代码

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
ll n, a[200010], ans;
bool st[200010];
char s[200010];
ll dp[200010];
int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	cin >> s + 1;
	for (int i = 2; i <= n; i++) {
		dp[i] = dp[i - 1];
		if (s[i] != s[i - 1]) {
			dp[i] = max(dp[i - 1], dp[i - 2] + a[i] + a[i - 1]);
		}
	}
	cout << dp[n] << endl;
	return 0;
}

3.小红的俄罗斯方块

题目描述

小红正在玩一个奇怪的俄罗斯方块游戏。已知这个俄罗斯方块只有以下一种图形:
 


 

这个图形可以顺时针不旋转,旋转90度、180度、270度,分别变成以下四种情况:


当图形无法下落的时候,会停住不动。
请注意,这个俄罗斯方块没有消除的情况。也就是说会越累积越高。
假设游戏共有 8 列,高度是无限的。请你输出最终每一列的高度。

输入描述:

第一行输入方块的数量 n。
接下来的 n 行,每行输入两个正整数 a 和 b,分别代表方块旋转的角度以及从哪一列下落的。方块是顺序下落的,也就是说前一个方块落到底之前,后一个方块不会开始下落。
1≤n≤100
a 一定是 0、90、180、270四个中的一个,b 代表方块的左端那一列,保证右端不会超过8。也就是说,若 a为0或180,1≤b≤7若a为 90或270,1≤b≤6

输出描述:

输出 8 个正整数,分别代表最终8列的高度。

示例1

输入

3
0 1
90 2
180 4

输出

3 3 3 4 4 0 0 0

说明

第一个方块下落后,地图变成了这样:

第二个方块下落后,地图变成了这样:

第三个方块下落后,地图变成了这样:

最终,8列的高度为:3 3 3 4 4 0 0 0

思路

简单的模拟问题

代码

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
ll n;
ll a, b;
ll h[10];
int main()
{
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> a >> b;
		if (a == 0) {
			ll base = max(h[b], h[b + 1]);
			h[b] = base + 3;
			h[b + 1] = base + 1;
		}
		else if (a == 90) {
			int base = max(max(h[b], h[b + 1] - 1), h[b + 2] - 1);
			h[b] = base + 2;
			h[b + 1] = base + 2;
			h[b + 2] = base + 2;
		}
		else if (a == 180) {
			int base = max(h[b] - 2, h[b + 1]);
			h[b] = base + 3;
		    h[b + 1] = base + 3;
		}
		else if (a == 270) {
			int base = max(max(h[b], h[b + 1]), h[b + 2]);
			h[b] = base + 1;
			h[b + 1] = base + 1;
			h[b + 2] = base + 2;
		}
	}
	for (int i = 1; i <= 8; i++) {
		cout << h[i] << " ";
	}
	return 0;
}

4.小红打怪

题目描述

已知地图上有 n 只怪物,每只怪物的血量是 ai,攻击力是 bi。小红准备去地图上探险杀怪,她的初始血量为 h。
小红有两个技能:
1. 普通攻击:对一只怪物造成1点伤害。
2. 强力攻击:对一只怪物造成2点伤害。
但是强力攻击是有冷却时间的。释放一个强力攻击后,需要2回合冷却(即释放2次普通攻击后)才能再次释放。
小红每次攻击后,若怪物没有死亡(即血量大于0),小红都会承受一次怪物攻击力的伤害。但是小红可以在战斗开始前喝血药,每个血药可以回复 k 点血量。也就算说, x 瓶血药可以将小红的初始血量提高到 h+x∗k

已知每只怪物都是不可复活的,当小红血量为0或负数时死亡。小红选择打一个怪时,在该怪物被打死之前不会更换目标。

当小红打死一只怪物去寻找另外一只怪物的过程中,我们可以认为强力攻击的冷却已经恢复完毕。

请问,小红初始带了 x 瓶血药时,最多可以击杀多少只怪物?

上述问题会重复 q次,每次询问都是独立的,小红初始的血瓶数量可能不同。

输入描述:

第一行输入三个正整数 n,h,k,代表地图上怪物的数量、小红的初始血量,以及小红每瓶血药可以回复的血量。
接下来的 n 行,每行输入两个正整数 ai 和 bi​,代表地图上每只怪物的血量和攻击力。
接下来的一行输入一个正整数 q,代表询问次数。
接下来的一行,输入 q 个正整数 x,代表每次询问中小红携带的血药数量。
1≤n,q,h,k,ai,bi,x≤10^5

输出描述:

输出一行 q 个正整数,代表小红携带 x 瓶血药时能击杀的最多怪物数量。

示例1

输入

3 1 2
5 1
5 2
3 2
3
1 2 3

输出

1 1 2

说明

第一只怪物小红需要攻击4次才能杀死,所以会被怪物打3下,掉血为1*3=3。
第二只怪物小红需要攻击4次才能杀死,所以会被怪物打3下,掉血为2*3=6。
第三只怪物小红需要攻击2次才能杀死,所以会被怪物打1下,掉血为2*1=2。
当小红携带1瓶血药时,可以先将血量回复至3点,然后击杀第三只怪物,剩余血量为1。
当小红携带2瓶血药时,无法击杀两只怪物。
当小红携带3瓶血药时,可以击杀第一只、第三只怪物。

思路

考察前缀和和二分,此处二分利用了algorithm包下的lower_bound函数,可以得到数组中大于等于一个值的最小下标

用c数组记录每一只怪物需要攻击几次才能杀死,d数组记录每个怪物会让小红掉多少滴血,对d数组从小到大排序,再对d数组进行前缀和,最后利用二分函数计算最多杀敌数量

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
ll n, h, k;//怪物的数量,小红的初始血量,小红每瓶血药可以回复的血量
ll a[100010], b[100010];//怪物的血量和攻击力
ll q, x;
int l[100010];
ll s[100010];
int p;
ll ans;
ll c[100010], d[100010];
ll gong(ll i) {
	return lower_bound(s, s + 100010, i) - s + 1;
}
int main()
{
	for (int i = 0; i < 100010; i++) {
		if (p % 3 == 0) {
			l[i] = 2;
		}
		else if (p % 3 == 1) {
			l[i] = 1;
		}
		else if (p % 3 == 2) {
			l[i] = 1;
		}
		p++;
	}
	s[0] = 2;
	for (int i = 1; i < 100010; i++) {
		s[i] += s[i - 1] + l[i];
	}
	cin >> n >> h >> k;
	for (int i = 0; i < n; i++) {
		cin >> a[i] >> b[i];
		c[i] = gong(a[i]);
		d[i] = (c[i] - 1) * b[i];
	}
	cin >> q;
	sort(d, d + n);
	for (int i = 1; i < n; i++) {
		d[i] += d[i - 1];
	}
	for (int i = 0; i < q; i++) {
		cin >> x;
		int pp = lower_bound(d, d + n, h + k * x) - d;
		cout << pp << " ";
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JalenG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值