A. Three Friends
题意:x轴上站了三个人,每个人都在一个坐标上(坐标可以相同)。每个人可以向左走一步,或者向右走一步,或者不动,问移动后两两之间的距离和的最小值。
题解:一共只有3x3x3种可能,直接暴力即可。小失误是minans
一开始赋值为了0x3f3f3f3f
,这是int
的最大值,而不是long long int
的。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int main() {
int q; cin >> q;
while (q--) {
ll a, b, c;
cin >> a >> b >> c;
ll minans = abs(a-b)+abs(a-c)+abs(b-c);
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
for (int k = -1; k <= 1; k++) {
ll na = a+i, nb = b+j, nc = c+k;
ll tmp = abs(na - nb) + abs(na - nc) + abs(nb - nc);
minans = min(minans, tmp);
}
}
}
cout << minans << endl;
}
return 0;
}
B. Snow Walking Robot
题意:一个机器人站在(0,0)位置,输入一串指令,指令可以控制它移动,但是如果机器人经过同一个位置(除了原点)超过两次就会损坏。现在可以删去这串指令里的一部分,并将它重新排列,使得机器人不会损坏,并且能够回到原点,问更改后的最长的指令序列是什么。
题解:符合要求的路线都可以等价于矩形路线,于是只需要记录“LRUD”分别出现了多少次,然后取LR出现的较小次数就是矩形的长,矩形的宽同理。当有一边为0时需要特判。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int main() {
int q; cin >> q;
while (q--) {
string s; cin >> s;
int l = 0, r = 0, u = 0, d = 0;
for (char c : s) {
if (c == 'L') l++;
if (c == 'R') r++;
if (c == 'U') u++;
if (c == 'D') d++;
}
int a, b;
a = min(l, r);
b = min(u, d);
if (a == 0 && b == 0) {
;
} else if (a == 0) {
b = 1;
} else if (b == 0) {
a = 1;
}
cout << 2*(a+b) << endl;
for (int i = 0; i < a; i++) {
cout << 'R';
}
for (int i = 0; i < b; i++) {
cout << 'D';
}
for (int i = 0; i < a; i++) {
cout << 'L';
}
for (int i = 0; i < b; i++) {
cout << 'U';
}
cout << endl;
}
return 0;
}
C. Yet Another Broken Keyboard
题意:给出一个字符串和一些字符,问在这个字符串中有多少个子串仅包含这些字符。
题解:长度为n的字符串的子串的个数为n*(n+1)/2
。只需要将原字符串切割成几个小字符串,将不包含在给定字符里的字符切割掉。剩余的字符串的子串都是合法的。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int main() {
int n, k; cin >> n >> k;
string s; cin >> s;
map<char, int> mp;
for (int i = 0; i < k; i++) {
char ch; cin >> ch;
mp[ch]++;
}
ll cnt = 0, ans = 0;
for (int i = 0; i < s.size(); i++) {
if (mp[s[i]] == 0) {
ans += cnt*(cnt+1)/2;
cnt = 0;
} else {
cnt ++;
}
}
ans += cnt*(cnt+1)/2;
cout << ans << endl;
return 0;
}
D. Remove One Element
题意:给定一个数组,最多可以移除一个元素,问这个数组中最长单调递增子串的长度。
题解:f(i)代表以i结尾的最长单调递增子串的长度。g(i)代表以i开头的最长单调递增子串的长度。先求出所有元素的f(i)和g(i),其中的最大值就是不删元素时的最长单调递增子串长度。
再考虑删掉第i个元素时的情况。如果删掉第i个元素,并且 a[i-1] < a[i+1] 那么就说明可以组合出新的单调递增子串,它的长度为f(i-1)+g(i+1)。将它与不删除元素时的最大值比较就能得出答案。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 2e5+7;
int f[N], g[N], a[N];
int main() {
int n; cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
f[0] = 1;
int ans = 0;
for (int i = 0; i < n; i++) {
if (a[i] > a[i-1]) f[i] = f[i-1] + 1;
else f[i] = 1;
ans = max(ans, f[i]);
}
g[n-1] = 1;
for (int i = n-2; i >= 0; i--) {
if (a[i] < a[i+1]) g[i] = g[i+1] + 1;
else g[i] = 1;
}
for (int i = 1; i < n-1; i++) {
if (a[i-1] < a[i+1] && f[i-1] + g[i+1] > ans) ans = f[i-1] + g[i+1];
}
cout << ans << endl;
return 0;
}