A. Sublime Sequence (800)
题目大意:数字 x,-x,x,-x,... 求和
解决思路:循环累加即可
#include <iostream>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int x, n;
cin >> x >> n;
int sum = 0;
while (n--) {
sum += x;
x = -x;
}
cout << sum << endl;
}
return 0;
}
B. Lasers (800)
题目大意:从(0, 0)走向(x, y), 其中有 n 条横向和 m 条纵向的激光,问至少要穿过多少个激光线。
解题思路:横向 + 纵向的数量之和
#include <iostream>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n, m, x, y;
cin >> n >> m >> x >> y;
int a, b;
for (int i = 0; i < n; i++) {
cin >> a;
}
for (int i = 0; i < m; i++) {
cin >> b;
}
cout << n + m << endl;
}
return 0;
}
C. Pacer (900)
题目大意:从地点 0 和 1 来回移动,且移动 1 次得 1 分;第 0 分钟在位置 0,规定了第几分钟要在哪个位置,问经过 n 分钟,最多能得多少分。
解题思路:可以把 n 分钟分成多干段,每一段求最大得分,加起来就是最大得分。
#include <iostream>
using namespace std;
int main() {
int t;
cin >> t;
int MAX_N = 200000 + 10;
int a[MAX_N], b[MAX_N];
while (t--) {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i] >> b[i];
}
a[0] = 0;
b[0] = 0;
int sum = 0;
for (int i = 1; i <= n; i++) {
int d = a[i] - a[i - 1];
if (b[i] == b[i - 1]) {
if (d % 2 == 1) {
sum += d - 1;
} else {
sum += d;
}
} else {
if (d % 2 == 1) {
sum += d;
} else {
sum += d - 1;
;
}
}
}
cout << sum + m - a[n] << endl;
}
return 0;
}
D. Destruction of the Dandelion Fields (1000)
题目大意:有 n 个整数,有一个收割机,一开始是关闭状态,如果遇到奇数状态会转换(开启和关闭相互转换),遇到偶数则不会;问收割机经过所有得数字,问收割之和最大多少,经过得顺序随意。
解题思路:
1、如果都是偶数,则为 0,因为没有开启的机会。
2、如果存在奇数,则偶数一定都可以做贡献。所以只需要考虑所有的奇数按照什么样的顺序收购即可:按照一大一小收割。
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int> b;
long long sum = 0;
for (int i = 0; i < n; i++) {
int a;
cin >> a;
if (a % 2 == 0) {
sum += a;
} else {
b.push_back(a);
}
}
if (b.size() == 0) {
cout << 0 << endl;
} else {
int m = b.size();
sort(b.begin(), b.end());
for (int i = m - 1; i >= m / 2; i--) {
sum += b[i];
}
cout << sum << endl;
}
}
return 0;
}
E. Split (1200)
题目大意:有一个数组,问有多少个子数字是好的。
解决思路:
1、 不可能枚举所有的子数组,2*n 次幂,复杂度太大。
2、 可以采用滑动窗口,累计计算满足条件的个数。
#include <iostream>
#include <vector>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n, k;
cin >> n >> k;
int a[n + 10];
vector<int> cnt(n + 10, 0);
for (int i = 0; i < n; i++) {
cin >> a[i];
cnt[a[i]]++;
}
long long res = -1;
for (int i = 1; i <= n; i++) {
if (cnt[i] % k != 0) {
res = 0;
break;
} else {
cnt[i] /= k;
}
}
if (res == 0) {
cout << res << endl;
continue;
}
res = 0;
// 滑动窗口
int left = 0;
vector<int> window(n + 10, 0);
for (int right = 0; right < n; right++) {
window[a[right]]++;
while (window[a[right]] > cnt[a[right]]) {
window[a[left]]--;
left++;
}
res += right - left + 1;
}
cout << res << endl;
}
return 0;
}
F. Gravity Falls (1800)
题目大意:有 n 个数组,可以按照任意顺序从低到高水平排序,由于重力的作用,上面数字的元素会往下掉,问第一层的序列字典序最小是多少。
解题思路:
1、先按照第 0 个元素从小到大排序,则第一个数组元素字典序肯定最小,全部加到答案中,假设有 m 个。
2、然后纵向将所有的数字前 m 个元素去掉,又形成了新的数组序列。
然后按照(1)(2)反复操作,最终得到答案。
一开始以为只排序第一次就行
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<vector<int>> a(n);
int max_k = 0;
for (int i = 0; i < n; i++) {
int k;
cin >> k;
for (int j = 0; j < k; j++) {
int b;
cin >> b;
a[i].push_back(b);
}
max_k = max(max_k, k);
}
vector<int> res;
while (res.size() < max_k) {
// cout << "aaa: " << a.size() << endl;
// for (int i = 0; i < a.size(); i++) {
// for (int j = 0; j < a[i].size(); j++) {
// cout << a[i][j] << ' ';
// }
// cout << endl;
// }
sort(a.begin(), a.end());
for (size_t i = 0; i < a[0].size(); i++) {
res.push_back(a[0][i]);
}
size_t begin = a[0].size();
vector<vector<int>> a_copy;
for (int i = 0; i < a.size(); i++) {
vector<int> tmp;
for (int j = begin; j < a[i].size(); j++) {
tmp.push_back(a[i][j]);
}
if (!tmp.empty()) {
a_copy.push_back(tmp);
}
}
a = a_copy;
}
for (size_t i = 0; i < res.size(); i++) {
cout << res[i] << " ";
}
cout << endl;
}
return 0;
}
G. Farmer John's Last Wish (1900)
看起来有点难