A
a题题意就是说给你一串字符串,然后从A~Z要思考1~26分钟来解决,最开始会给你一个竞赛持续时间,也就是说你最多思考多久,然后一个题要解决的话,那么他在这场比赛中出现的次数就必须大于等于解决他的时间,所以我们用桶排序的思想来计数并判断就好了
#include<bits/stdc++.h>
using namespace std;
void solve()
{
int n; cin >> n;
string s; cin >> s;
vector<int>v(26,0);
int x = s.size();
int ans = 0;
for (int i = 0; i <= x-1; ++i)
{
v[s[i] - 'A']++;//这个问题出现了几次
}
for (int i = 0; i <= 25; ++i)
{
if (v[i] >= i + 1)ans++;//如果出现次数大于等于解决他所需要的时间,这个题目就被解决了
}
cout << ans << '\n';
}
int main()
{
int _; cin >> _;
while (_--)solve();
}
B
b题我们取几个样例进行分析
比如第一个样例,6 2,那么原数组就是1,2,3,4,5,6我们要出现有且仅有两对的顺序数对,其他都是逆序,那么我们可以这么排序
5 6,3,4,2,1
此时5,6,3,4就是我们需要的答案,就是可以两个两个从数组最后开始取,等到k取完了我们就可以逆序输出数组的剩下元素了
当然,我们还要考虑2*k>n的情况,这个时候我们没法凑出全部的数对
样例中的样例2不太好考虑,我们自己编一个:)
6 4
看这个数组1,2,3,4,5,6
要出现四个顺序数对,因为n<2K我们只能考虑连续顺序数对
那么我们就可以3,4,5,6,2,1就可以了
换句话说,我们可以逆序输出后面剩余的,在顺序输出前面K+1的就行力
代码
#include<bits/stdc++.h>
using namespace std;
void solve()
{
int n, k; cin >> n >> k;
vector<int>a(n + 1);
for (int i = 1; i <= n; ++i)a[i] = i;
int i = n - 2;//从倒数第二个数开始输出
int cnt = n - 2 * k;//cnt记录要逆序输出的数目
if (n >= 2 * k)
{
while (k--)
{
for (int j = 1; j <= 2; j++)cout << a[i + j] << ' ';//保证只输出两个数
i -= 2;//每次运行时记得要i-=2,保证第一次输出的是n-1,n,第二次就是n-3,n-2两个数
}
for (int w = cnt; w >= 1; --w)cout << a[w] << ' ';//逆序输出剩余的元素
cout << '\n';
}
else
{
int res = n - k - 1;
for (int i = n; i > n - res; --i)cout << a[i] << ' ';//先从后面输出剩余的逆序数组
for (int i = 1; i <= k+1; ++i)cout << a[i] << ' ';//输出满足答案所需的顺序数组
cout << '\n';
}
}
int main()
{
int _; cin >> _;
while (_--)solve();
}
C
c题看上去很麻烦,其实想清楚了也是一个暴力枚举能够解决的问题,我们可以枚举最多只算到ai的情况,比如我们能解决k个问题,那么我们可以考虑做一次a1,然后在做k-1次a1,或者说做一次a1,一次a2,再在a1,a2里面选出再次做经验值最大的情况做k-2次这样枚举.
#include<bits/stdc++.h>
using namespace std;
void solve()
{
int n, k; cin >> n >> k;
vector<int>arr(n), brr(n);
for (int i = 0; i < n; ++i) cin >> arr[i];
for (int i = 0; i < n; ++i) cin >> brr[i];
int maxb = brr[0], sum = 0, realsum = 0;
for (int i = 0; i < min(n, k); ++i)//从nk中选最小的进行遍历
{
sum += arr[i];//首先先加上遍历时所有任务做第一次获得的经验值
maxb = max(brr[i], maxb);//获取再次做任务里面能获得的最大经验值
realsum = max(sum + maxb * (k - i - 1), realsum);//在更新realsum得到最终结果
}
cout << realsum << '\n';
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int _; cin >> _;
while (_--)solve();
}
D
d题的题意很简单,但是实现起来还是比较麻烦的,可以用dp(但是我不会(大悲)),因为就只有三个数,我们也可以直接考虑暴力列出可能性来计算最大值
这题代码应该还是比较好懂的,大家自行看看,要是还不懂可以再问:)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e8 + 5;
struct active
{
int idx;
int num;
};//定义结构体记录下标和值
bool cmp(active a,active b)
{
return a.num > b.num;
}//定义cmp函数,规定排序原则
void solve()
{
int n; cin >> n;
vector<active>a(n), b(n), c(n);
for (int i = 0; i <= n-1; ++i)
{
cin >> a[i].num;
a[i].idx = i;
}
for (int i = 0; i <= n-1; ++i)
{
cin >> b[i].num;
b[i].idx = i;
}
for (int i = 0; i <= n-1; ++i)
{
cin >> c[i].num;
c[i].idx = i;
}
sort(a.begin(), a.end(), cmp);
sort(b.begin(), b.end(), cmp);
sort(c.begin(), c.end(), cmp);//排序过后,我们最多选择三天,就算天数冲突了我们也最多列到每个数组的第三项
int sum = 0;
for (int i = 0; i <= 2; ++i)
for (int j = 0; j <= 2; ++j)
for (int k = 0; k <= 2; ++k)
if (a[i].idx != b[j].idx && a[i].idx != c[k].idx && b[j].idx != c[k].idx)//如果进行活动没有冲突,就记录这种情况,并且计算最大值
sum = max(sum, a[i].num + b[j].num + c[k].num);
cout << sum << '\n';
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int _; cin >> _;
while (_--)solve();
}