A. Linear Keyboard
题目大意
第一行给你一个长度为26的字符串,代表26个字母的排列循序,相邻字母的距离为 1 。
第二行给你一个字符串,问从头走到尾共走了多长的距离。
解题思路
暴力枚举即可。
AC代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t; scanf("%d", &t);
while (t--)
{
string s1, s2;
cin >> s1 >> s2;
int ans = 0;
for (int i = 1; i < s2.size(); i++)
{
int k = s1.find(s2[i]) - s1.find(s2[i - 1]);
ans += abs(k);
}
cout << ans << endl;
}
return 0;
}
B. Odd Grasshopper
题目大意
给你一个起始坐标 x ,给你一个跳跃的次数 n 。第 i 次跳跃的长度为 i。然后跳跃的方向取决于跳跃位置的奇偶性,偶数向左跳跃,奇数向右跳跃,问最后的位置。
解题思路
对 x 的奇偶性分类讨论,找规律。
AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
int main()
{
int t; scanf("%d", &t);
while (t--)
{
ll x, n; scanf("%lld%lld", &x, &n);
ll ans;
if (x % 2 == 0)
{
if (n % 4 == 0) ans = x;
if (n % 4 == 1) ans = x - n;
if (n % 4 == 2) ans = x + 1;
if (n % 4 == 3)ans = n + 1 + x;
}
else
{
if (n % 4 == 0) ans = x;
if (n % 4 == 1) ans = x + n;
if (n % 4 == 2) ans = x - 1;
if (n % 4 == 3) ans = x - 1 - n;
}
cout << ans << endl;
}
return 0;
}
C. Minimum Extraction
题目大意
给你一个长度为n的数组,每次从数组中找到最小的元素 x ,然后删除该元素,并将剩余元素都 - x,直到数组的长度为1。求每次变化后数组中最小元素的最大值。
解题思路
设一个排好序的数组:A1 A2 A3 A4 A5 。
第一步操作:A1 A2 A3 A4 A5
第二步操作:A2-A1 A3-A1 A4-A1 A5-A1
第三步操作:A3-A2 A4-A2 A5-A2
第四步操作:A4-A3 A5-A3
第五步操作:A5-A4
综上:答案为 max(A1, A2-A1, A3-A2, A4-A3, A5-A4)
AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int n;
int a[N];
int main()
{
int t; scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
sort(a + 1, a + 1 + n);
int mx = a[1];
for (int i = 1; i <= n; i++) mx = max(mx, a[i] - a[i - 1]);
printf("%d\n", mx);
}
return 0;
}
D. Blue-Red Permutation
题目大意
给你一个长度为n的数组,然后再给你一个长度为n的字符串,字符串由‘B’和‘R’组成,数组中每一个元素与字符串想对应,若对应的字符为‘B’,代表该元素每次可以减少1,反之若对应‘R’,代表该元素每次可以增加1,次数不限。问是否可以将该数组变成1~n的排列。
解题思路
这是一道贪心的题目。
设蓝色元素的个数为len1,红色元素的个数为len2.
判断所有蓝色元素是否能组成1~len1,所有红色元素是否能组成len+1 ~ n。若不能则答案为NO,反之为YES。
AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int a[N];
int main()
{
int t; cin >> t;
while (t--)
{
vector<int> blue, red;
int n; scanf("%d", &n);
for (int i = 0; i < n; i++) scanf("%d", &a[i]);
string s; cin >> s;
for (int i = 0; i < n; i++)
{
if (s[i] == 'B') blue.push_back(a[i]);
else red.push_back(a[i]);
}
sort(blue.begin(), blue.end());
sort(red.begin(), red.end(), greater<int>());
bool bug = true;
for (int i = 0; i < blue.size(); i++)
{
if (blue[i] <= i)
{
bug = false;
break;
}
}
for (int i = 0; i < red.size(); i++)
{
if (red[i] > n - i)
{
bug = false;
break;
}
}
puts(bug ? "YES" : "NO");
}
return 0;
}
E. Robot on the Board 1
题目大意
给你一个n * m 的网格,再给你一个字符串,代表机器人的行走路径,机器人不能走出网格,问机器人从那个位置开始走才能使行走的距离更长。
解题思路
暴力枚举即可,分别用四个变量mn1,mx1,mn2,mx2记录一下向左向右向上向下走的最远距离。当mx1-mn1+1>m或者mx2-mn2+1>n时跳出循环。
AC代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t; cin >> t;
while (t--)
{
int n, m; scanf("%d%d", &n, &m);
string s; cin >> s;
int mn1 = 0, mn2 = 0, mx1 = 0, mx2 = 0;
int h = 0, l = 0;
for (int i = 0; i < s.size(); i++)
{
if (s[i] == 'R') h++;
if (s[i] == 'L') h--;
if (s[i] == 'U') l++;
if (s[i] == 'D') l--;
mn1 = min(mn1, h);
mx1 = max(mx1, h);
mn2 = min(mn2, l);
mx2 = max(mx2, l);
if (mx1 - mn1 + 1 > m)
{
if (s[i] == 'R') mx1--;
else mn1++;
break;
}
if (mx2 - mn2 + 1 > n)
{
if (s[i] == 'U') mx2--;
else mn2++;
break;
}
}
printf("%d %d\n", 1 + mx2, 1 - mn1);
}
return 0;
}