Codeforces Round 916 (Div
Codeforces Round 916 (Div. 3)
题目地址Codeforces Round 916 (Div. 3)
标称给出了伪代码,完整代码模板在最后一题。
Problems A. Problemsolving Log
思路
给出一个字符串,字符串包含\(A-Z\),表示\(26\)个问题,\(A-Z\)的难度分别为\(1-26\)。字符串第\(i\)个位置出现的问题表示当前在思考该问题。解决每个问题需要思考该问题的时间大于等于其难度,因此直接用一个map来记录即可,当该问题被解决后,将其赋值为\(-INF\)。
标程
void Solved() {
int n; cin >> n;
string s; cin >>s;
int res = 0;
map<char, int> mp;
for(int i = 0; i < n; i ++ ) {
mp[s[i]] ++;
if(mp[s[i]] >= s[i] - 'A' + 1) {
res ++;
mp[s[i]] = -INF;
}
}
cout << res << endl;
}
Problems B. Preparing for the Contest
思路
题目给定两个整数\(n,k\),分别表示有元素为\(1-n\)的数列,\(k\)表示数列中有\(k\)个\(a_i < a_{i+ 1}\)的组合。要求输出符合题目要求的数组排列。
我们只需要顺序输出前\(k\)个元素然后逆序输出剩余元素即可得到。
标程
void Solved() {
int n, k; cin >> n >> k;
for(int i = 1; i <= k; i ++ ) {
cout << i << " ";
}
for(int i = n; i > k; i -- ) {
cout << i << " ";
}
cout << endl;
}
Problems C. Quests
思路
题目给定\(n,k\),表示有编号为\(1-n\)的\(n\)个任务,然后Monocarp可以完成\(k\)个任务,每个任务可重复完成。
每个任务有两个经验值,第一个经验值是第一次完成任务时能获得的经验值,第二个经验值是之后重复完成时每次能获得的经验值。
题目要求输出最大经验值。
我们考虑到完成第\(i\)个任务的前提是完成前\(i-1\)个任务。假设我们需要完成前\(i(i<k)\)个任务,那么至少需要完成\(i\)个任务,多余的任务我们可以选前\(i\)个任务中第二个经验值最大的任务来做。
那么结果为:\(res = MAX(\sum_{j=1}^{i}{a[j]}+c[i] \times(k-i-1))\),$0\le i \le MIN(n-1, k-1) $, \(i\)为枚举的前若干项,\(c[i]\)为前\(i\)中第二经验值的最大值。
标程
#define int long long
void Solved() {
int n, k; cin >> n >> k;
vector<int> a(n), b(n), c(n);
for(auto &i : a) cin >> i;
for(auto &i : b) cin >> i;
for(int i = 1; i < n; i ++ ) {
a[i] += a[i - 1];
}
int mx = 0;
for(int i = 0; i < n; i ++) {
if(b[i] > mx) c[i] = b[i], mx = b[i];
else c[i] = mx;
}
int res = 0;
for(int i = min(n - 1, k - 1); i >= 0; i -- ) {
res = max(res, a[i] + c[i] * (k - i - 1));
}
cout << res << endl;
}
Problems D. Three Activities
思路
给定三个长度为\(n\)的数组,要求从每个数组中选择一个数,要求选择的三个整数下标互不相同且总和最大。
所选的数字必定为三个数组中前三大的数字,因此用sort排个序,然后枚举一下所有可能,输出最大值即可。
标程
#define int long long
#define ALL(x) x.begin(), x.end()
bool cmp(PII n1, PII n2) {
return n1.fi < n2.fi;
}
void Solved() {
int n; cin >> n;
vector<PII> a(n), b(n), c(n);
vector<PII> x, y, z;
int res = 0;
for(int i = 0; i < n; i ++ ) {
cin >> a[i].fi; a[i].se = i;
}
for(int i = 0; i < n; i ++ ) {
cin >> b[i].fi; b[i].se = i;
}
for(int i = 0; i < n; i ++ ) {
cin >> c[i].fi; c[i].se = i;
}
sort(ALL(a)); sort(ALL(b)); sort(ALL(c));
for(int i = n - 3; i < n; i ++ ) {
for(int j = n - 3; j < n; j ++ ) {
if(a[i].se == b[j].se) continue;
for(int k = n - 3; k < n; k ++ ) {
if(a[i].se == c[k].se) continue;
if(b[j].se == c[k].se) continue;
res = max(res, a[i].fi + b[j].fi + c[k].fi);
}
}
}
cout << res << endl;
}
Problems E1&E2. Game with Marbles
思路
根据题目设置的游戏条件,每次一个人选择一个颜色的弹珠,然后将自己的该弹珠个数减一,并将对方的减为零,当有一方该颜色弹珠个数为零时不能选择改颜色。当所有颜色都不能选时游戏结束。Alice和Bob都希望游戏结束后自己的弹珠比对方的多。
容易发现,当前选择的最优解必然是选择两种玩家弹珠数之和最大的颜色。当选择两玩家弹珠数之和最大的颜色时,可令两玩家弹珠总和之差拉开最大。
按照最优方式,玩家选择的颜色顺序是根据两玩家该颜色总和降序来选,因此我们按照总和最大对颜色进行排序,然后进行遍历。
当为奇数步时,Alice选择,则\(res+=a[i].a-1\),因为此时\(a[i].b = 0\),因此\(a[i].a-1\)可以表示为这次选择将会拉开的差距。偶数步同上。
标程
#define int long long
#define ALL(x) x.begin(), x.end()
struct node {int a, b, c, x;};
bool cmp(node n1, node n2) {
return n1.c > n2.c;
}
void Solved() {
int n; cin >> n;
vector<node> a(n);
int res = 0;
for(auto &i : a) cin >> i.a;
for(auto &i : a) cin >> i.b;
for(int i = 0; i < n; i ++ ) {
a[i].c = a[i].a + a[i].b;
a[i].x = i;
}
sort(ALL(a), cmp);
for(int i = 0; i < n; i ++ ) {
if((i + 1) & 1) {
res += a[i].a - 1;
} else {
res -= a[i].b - 1;
}
}
cout << res << endl;
}
Problems F. Programming Competition
思路
给出\(n\)个节点,然后给出\(2-n\)的父节点,要求找出组合\((a,b)\),\(a,b\)相互不为其父节点或父节点的父节点的个数。
标程
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
#define LL long long
#define ULL unsigned long long
#define PII pair<int, int>
#define lowbit(x) (x & -x)
#define Mid ((l + r) >> 1)
#define ALL(x) x.begin(), x.end()
#define endl '\n'
#define fi first
#define se second
const int INF = 0x7fffffff;
const int Mod = 1e9 + 7;
const int N = 2e5 + 10;
vector<int> a[N];
int b[N], f[N];
void dfs(int u) {
int id = 0;
b[u] = f[u] = 1;
for(auto v : a[u]) {
dfs(v);
b[u] += b[v];
if(b[v] > b[id]) id = v;
}
f[u] = 1 + ((b[u] - 1) & 1);
if(f[id] > b[u] - 1 - b[id]) f[u] = 1 + f[id] - (b[u] - 1 - b[id]);
}
void Solved() {
int n; cin >> n;
for(int i = 1; i <= n; i ++ ) a[i].clear(), b[i] = f[i] = 0;
for(int i = 2; i <= n; i ++ ) {
int x; cin >> x;
a[x].push_back(i);
}
dfs(1);
cout << (n - f[1]) / 2 << endl;
}
signed main(void) {
IOS
int ALL = 1;
cin >> ALL;
while(ALL -- ) Solved();
// cout << fixed;//强制以小数形式显示
// cout << setprecision(n); //保留n位小数
return 0;
}

浙公网安备 33010602011771号