2023年 牛客周赛 Round 2题解

1. 小红的环形字符串

A-小红的环形字符串_牛客周赛 Round 2 (nowcoder.com)

2023年 牛客周赛 Round 2题解_第1张图片

题意是在一个环形字符串中找子串的个数——构造环形字符串可以将字符串s1加上字符串初始的一部分(长度为字符串s2长度减去1)。然后用substr在环形字符串中截取与s2等长的字串,将两者作比较,如果相等答案加1。

#include
#include

int main(){
	std::string s1, s2;
	std::cin >> s1 >> s2;
	for(std::size_t i = 0; i < s2.length() - 1; i++)	s1 += s1[i];
	
	int cnt = 0;
	for(std::size_t i = 0, len = s2.length(); i < s1.length(); i++){
		std::string s = s1.substr(i, len);
		if(s == s2)	cnt++;
	}
	std::cout << cnt << std::endl;
	return 0;
}

2. 相邻不同数字的标记

B-相邻不同数字的标记_牛客周赛 Round 2 (nowcoder.com)

2023年 牛客周赛 Round 2题解_第2张图片

 题意是记录相邻不同颜色的数字,统计它们的累加和,但是每个数字只能被统计一次。考虑到解是全局最优解,选择用动态规划——当连续两个字符不相同时(dp[i] = std::max(dp[i - 1], dp[i - 2] + a[i] + a[i - 1]))

#include
#include
using i64 = long long;
constexpr int N = 1e5 + 100;
int a[N];
i64 dp[N];
int main(){
	int n;
	std::cin >> n;
	for(int i = 0; i < n; i++)	std::cin >> a[i];
	
	std::string s;
	std::cin >> s;
	for(int i = 1; i < s.length(); i++){
		dp[i] = dp[i - 1];
		if(i < 1)	dp[i] = std::max(dp[i], dp[i - 1] + a[i] + a[i - 1]);
		else if(s[i] != s[i - 1])	dp[i] = std::max(dp[i - 1], dp[i - 2] + a[i] + a[i - 1]);
	}
	std::cout << dp[n - 1] << std::endl;
	return 0;
}

3. 小红的俄罗斯方块

C-小红的俄罗斯方块_牛客周赛 Round 2 (nowcoder.com)

2023年 牛客周赛 Round 2题解_第3张图片

 题意是,有一块L型的积木块?这个积木块可以旋转,然后从第b列落下,当所有的积木块全部落下时,询问每列的高度。 因为部分积木块可能下部会空缺,我们统计一下当积木块落下时候,被影响到的列的当前高度减去需要填补空缺的高度,取被影响到的列的最大值,然后加上这个积木块在每列的高度。

#include

constexpr int N = 10;
int h[N];

int main(){
	int n;
	std::cin >> n;
	while(n--){
		int a, b;
		std::cin >> a >> b;
		//不旋转
		if(a == 0){
			int base = std::max(h[b], h[b + 1]);
			h[b] = base + 3;
			h[b + 1] = base + 1;
		}
		//旋转90°
		else if(a == 90){
			int base = std::max(std::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;
		}
		//旋转180°
		else if(a == 180){
			int base = std::max(h[b] - 2, h[b + 1]);
			h[b] = base + 3;
			h[b + 1] = base + 3;
		}
		//旋转270°
		else{
			int base = std::max(std::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++)	std::cout << h[i] << " ";
	std::cout << std::endl;
	return 0;
}

4. 小红打怪

D-小红打怪_牛客周赛 Round 2 (nowcoder.com)

2023年 牛客周赛 Round 2题解_第4张图片

题意是balabala;因为小红可以进行一次伤害为2的技能攻击,之后技能会冷却两个回合——依据先用先CD原则,有技能就放是最好的情况。先统计出击杀每个怪物需要消耗的生命值,对其进行排序,求其前缀和,然后二分找出最终最多击杀怪物的个数。 

#include
#include
#include
#define int long long

signed main(){
	int n, h, k;
	std::vector v;
	std::cin >> n >> h >> k;
	for(int i = 1; i <= n; i++){
		int a, b;
		std::cin >> a >> b;
		int cnt = a / 4 * 3;
		int val = a % 4;
		if(val == 0)	cnt += 0;
		else if(val <= 2)	cnt += 1;
		else cnt += 2;
		v.push_back((cnt - 1) * 1ll * b );//如果怪物已经被击杀,那么最后一次的攻击不会发生
	}
	
	std::sort(v.begin(), v.end());
	std::vector s;
	int sum = 0;
	for(int i = 0; i < v.size(); i++){
		sum += v[i];
		s.push_back(sum);
	}
	
	int q;
	std::cin >> q;
	while(q--){
		int num; std::cin >> num;
		num = num * 1ll * k  + h;//计算小红嗑药后的血量
		int pos = std::lower_bound(s.begin(), s.end(), num) - s.begin();
		std::cout << pos << " ";
	}
	std::cout << std::endl;
	return 0;
}

你可能感兴趣的:(算法)