2024/1/14 周日
1.召唤神坤
哎哟,你干嘛。第一题就难倒了不少人,通过率惨不忍睹
【参考代码】
lanqiao4603010779 题目1的代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 100; // 定义常量N为200,001
int n; // 定义整数变量n
int a[N], pre[N], h[N]; // 定义整数数组a、pre和h,大小均为N
signed main()
{
cin >> n; // 从标准输入读取整数n的值
for(int i=1; i<=n; i++)
cin >> a[i]; // 循环读取n个整数并存储到数组a中
for(int i=1; i<=n; i++)
pre[i] = max(pre[i-1], a[i]); // 计算前缀最大值数组pre
for(int i=n; i>=1; i--)
h[i] = max(h[i+1], a[i]); // 计算后缀最大值数组h
int maxn = 0; // 初始化最大值为0
for(int i=2; i<=n-1; i++) // 循环遍历数组a的元素,从索引2到n-1
{
maxn = max(maxn, (pre[i-1] + h[i+1]) / a[i]); // 更新最大值
}
cout << maxn << '\n'; // 输出最大值
// 用于分析:
// for(int i=1; i<=n; i++)
// cout << pre[i] << " ";
// cout << '\n';
//
// for(int i=1; i<=n; i++)
// cout << h[i] << " ";
// cout << '\n';
return 0; // 返回0表示程序正常结束
}
【代码分析】
这题很坑爹,因为测试数据的序列不一定是单调递增的,所以需要枚举找出最大值。
学校大佬写的代码:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> a(n, 0);
for (int i = 0; i < n; i++)
cin >> a[i];
vector<int> left(n, 0);
vector<int> right(n, 0);
// 计算数组left的值,left[i]表示从左到右遍历到第i个元素时,以该元素为最小值的最大子序列和
left[1] = a[0];
for (int i = 2; i < n; i++)
left[i] = max(a[i - 1], left[i - 1]);
// 计算数组right的值,right[i]表示从右到左遍历到第i个元素时,以该元素为最小值的最大子序列和
right[n - 2] = a[n - 1];
for (int i = n - 3; i >= 0; i--)
right[i] = max(right[i + 1], a[i + 1]);
int ans = 0;
// 遍历数组a,计算以每个元素为最小值的最大子序列和,并更新答案ans
for (int i = 1; i < n - 2; i++)
ans = max(ans, (right[i] + left[i]) / a[i]);
cout << ans << endl;
return 0;
}
2.聪明的交换策略
【参考代码】
自己推出来的,交换过程类似冒泡排序,记录次数即可。冒泡排序时间复杂度太高,数据量一大就会超过运行时间
⚠️只能通过33.3%测试用例!可以拿一点分
#include <iostream>
using namespace std;
#include <string>
int main()
{
// 请在此输入您的代码
int n;
int tmp;
int count = 0;
string s;
cin >> n;
cin >> s;
for(int i=0; i<n-1; i++)
{
for(int j=0; j<n-1-i; j++)
{
if(s[j] > s[j+1])
{
tmp = s[j];
s[j] = s[j+1];
s[j+1] = tmp;
count++;
}
}
}
cout << count;
return 0;
}
100%参考代码:
受到其他同学的启发,数1和数0的个数,用前缀和处理结果,最后取最小值。
#include <iostream>
using namespace std;
#include <string>
int main()
{
int n;
int ans1=0, ans2=0;
int count = 0;
string s;
// 输入字符串长度和字符串本身
cin >> n;
cin >> s;
// 遍历字符串,统计0的连续个数之和
for(int i=0; i<n; i++)
{
if(s[i] == '0')
count++;
else
ans1 += count;
}
// 重置count为0,重新遍历字符串,统计1的连续个数之和
count = 0;
for(int i=0; i<n; i++)
{
if(s[i] == '1')
count++;
else
ans2 += count;
}
// 输出0的连续个数之和和1的连续个数之和中的较小值
cout << min(ans1, ans2);
return 0;
}
3.怪兽突击
4.蓝桥快打
【参考代码】
要注意,小桥秒杀情况先处理。
这题是算回合的,小蓝先手,如果他和小桥一样的攻击值,能否将小桥KO。
考虑小蓝血量小于小桥就行了,算回合要向上取整。
小桥在回合数(round)归零之后必须血量为0,不为0就加1。用取余判断
#include <iostream>
using namespace std;
int main()
{
// 请在此输入您的代码
int n;
cin >> n;
for(int i=0; i<n; i++)
{
int a, b, c;
cin >> a >> b >> c;
if(c >= a) //小蓝被秒杀情况
cout << b << endl;
else
{
int round = 0; //回合
if(a % c != 0)
round = (a / c) + 1;
else
round = (a / c);
if(b % round != 0)
cout << (b / round) +1 << endl;
else
cout << (b / round) << endl;
}
}
return 0;
}
大佬【懵逼的迷路人】的代码:
只有14行。思路一样,先算小蓝被KO之前能打的回合数(a[0] / a[2]),向上取整就不用取余判断。再算小蓝在这么多回合需要多少攻击值。
这个代码不用另外判断秒杀情况,因为秒杀情况回合数为1,a[0] / a[2] = 1。小桥血量除以回合数就是攻击值👍👍👍
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int t;
double a[3] = {0}; // 不用int可以在下面少一步强制类型转换
cin >> t;
while (t--) {
cin >> a[0] >> a[1] >> a[2];
cout << int(ceil(a[1] / ceil(a[0] / a[2]))) << endl; // ceil是向上取整函数
}
return 0;
}