Codeforces Round 1057 (Div. 2) A~D
A. Circle of Apple Trees
模拟。
可以一直循环,那么将原数组去重排序后,第 \(i\) 轮吃第 \(i\) 个就可以把所有不同的数字都吃掉,即答案就是去重后的元素个数。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
void solve() {
int n;
std::cin >> n;
int ans = 0;
std::vector<int> b(n + 1);
for (int i = 0; i < n; i += 1) {
int x;
std::cin >> x;
ans += b[x] == 0;
b[x] += 1;
}
std::cout << ans << "\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
B - Bitwise Reversion
思维,位运算。
设 \(a\& b = X,\ b\& c = Y\),那么有 \((a\& b)\& (b\&c)=X\&Y=a\&b\&c\),同理可得 \((a\& b)\& (b\&c)=(a\& b)\& (a\&c)=(a\& c)\& (b\&c)\),即满足 \(a\&b=a\&c=b\&c\) 即可。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
void solve() {
int x, y, z;
std::cin >> x >> y >> z;
std::cout << ((x & y) == (y & z) && (x & z) == (x & y) ? "YES\n" : "NO\n");
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
C - Symmetrical Polygons
分类讨论。
满足多边形的条件之一是任意边都需要小于其他边之和。
要形成对称轴,显然偶数条边都是可以选的,记偶数条边的和为 \(sum\),对对称轴穿过几条边分类讨论:
- 穿过两个顶点,即穿过零条边:此时答案等于 \(sum\),但前提偶数条边大于 \(2\)。
- 穿过一条边:枚举奇数边 \(x\),取最大满足 \(x<sum\) 的 \(x+sum\)。
- 穿过两条边:枚举奇数边 \(x\),找最大满足 \(y<x+sum\) 的 \(y\),且 \(x<y+sum\),此时取最大的 \(x + y + sum\)。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
void solve() {
int n;
std::cin >> n;
std::map<int, int> mp;
std::vector<int> a(n);
for (int i = 0; i < n; i += 1) {
std::cin >> a[i];
mp[a[i]] += 1;
}
i64 res = 0;
int use = 0, used = 0;
std::set<i64> has;
for (auto &[x, y] : mp) {
int k = y - (y % 2);
res += 1LL * x * k;
use += k;
if (y & 1) {
has.insert(x);
}
}
i64 ans = use > 2 ? res : 0;
for (auto &x : has) {
if (x < res) {
ans = max(ans, res + x);
}
}
std::vector<int> vec(has.begin(), has.end());
for (auto x : vec) {
has.erase(x);
auto t = has.lower_bound(x + res);
if (t != has.begin() && x < res + *prev(t)) {
t = prev(t);
ans = max(ans, res + x + *t);
}
has.insert(x);
}
std::cout << ans << "\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
D - Not Alone
\(dp\)。
这个漂亮数组可以分成若干个长度为 \(2\) 或 \(3\) 的值相同的子数组。
设 \(dp_i\) 表示将前 \(i\) 个数分成两种长度的子数组的最小代价,代价即是子数组的极值差,记为 \(cost\);那么有转移 \(dp_i=\min(dp_{i-2}+cost_{a_i,a_{i-1}},dp_{i-3}+cost_{a_i,a_{i-1},a_{i-2}})\)。
因为可以为环形,那么最多左移三次进行 \(dp\) 求最小值即可。
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for(int i = 0; i < n; i += 1) {
std::cin >> a[i];
}
const i64 inf = 1E15;
auto cost = [](int x,int y)->int{
return abs(x - y);
};
auto cost2 = [](int x,int y,int z)->int{
return std::max({x, y, z}) - std::min({x, y, z});
};
i64 ans = inf;
for(int x = 0; x < 3; x += 1) {
std::vector<i64> dp(n + 1, inf);
for(int i = 1; i < n; i += 1) {
dp[i] = std::min(dp[i], (i - 2 >= 0 ? dp[i - 2] : 0) + cost(a[i], a[i - 1]));
if(i >= 2){
dp[i] = std::min(dp[i], (i - 3 >= 0 ? dp[i - 3] : 0) + cost2(a[i], a[i - 1], a[i - 2]));
}
}
ans = std::min(ans, dp[n - 1]);
std::rotate(a.begin(), a.begin() + 1, a.end());
}
std::cout << ans << "\n";
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
std::cin >> t;
while (t--) {
solve();
}
return 0;
}

浙公网安备 33010602011771号