文章目录
- Problems A. Problemsolving Log
- 思路
- 标程
- Problems B. Preparing for the Contest
- 思路
- 标程
- Problems C. Quests
- 思路
- 标程
- Problems D. Three Activities
- 思路
- 标程
- Problems E1&E2. Game with Marbles
- 思路
- 标程
- Problems F. Programming Competition
- 思路
- 标程
题目地址Codeforces Round 916 (Div. 3)
标程给出了伪代码,完整代码模板在最后一题。
Problems A. Problemsolving Log
思路
给出一个字符串,字符串包含 A − Z A-Z A−Z,表示 26 26 26个问题, A − Z A-Z A−Z的难度分别为 1 − 26 1-26 1−26。字符串第 i i i个位置出现的问题表示当前在思考该问题。解决每个问题需要思考该问题的时间大于等于其难度,因此直接用一个map
来记录即可,当该问题被解决后,将其赋值为 − I N F -INF −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 n,k n,k,分别表示有元素为 1 − n 1-n 1−n的数列, k k k表示数列中有 k k k个 a i < a i + 1 a_i < a_{i+ 1} ai<ai+1的组合。要求输出符合题目要求的数组排列。
我们只需要顺序输出前 k k 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 n,k n,k,表示有编号为 1 − n 1-n 1−n的 n n n个任务,然后Monocarp可以完成 k k k个任务,每个任务可重复完成。
每个任务有两个经验值,第一个经验值是第一次完成任务时能获得的经验值,第二个经验值是之后重复完成时每次能获得的经验值。
题目要求输出最大经验值。
我们考虑到完成第 i i i个任务的前提是完成前 i − 1 i-1 i−1个任务。假设我们需要完成前 i ( i < k ) i(i<k) i(i<k)个任务,那么至少需要完成 i i i个任务,多余的任务我们可以选前 i i i个任务中第二个经验值最大的任务来做。
那么结果为: r e s = M A X ( ∑ j = 1 i a [ j ] + c [ i ] × ( k − i − 1 ) ) res = MAX(\sum_{j=1}^{i}{a[j]}+c[i] \times(k-i-1)) res=MAX(∑j=1ia[j]+c[i]×(k−i−1)),$0\le i \le MIN(n-1, k-1) $, i i i为枚举的前若干项, c [ i ] c[i] c[i]为前 i 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 n 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选择,则 r e s + = a [ i ] . a − 1 res+=a[i].a-1 res+=a[i].a−1,因为此时 a [ i ] . b = 0 a[i].b = 0 a[i].b=0,因此 a [ i ] . a − 1 a[i].a-1 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 n n个节点,然后给出 2 − n 2-n 2−n的父节点,要求找出组合 ( a , b ) (a,b) (a,b), a , b 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 secondconst 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) {IOSint ALL = 1; cin >> ALL;while(ALL -- ) Solved();// cout << fixed;//强制以小数形式显示// cout << setprecision(n); //保留n位小数return 0;
}