欢乐结训赛题解
A 题目链接
- 题目大意
给你一个字符串,让你求字符串中最大的字母在字母表中排第几 例如 codeforces 中 s 的是最大的 s在字母表中排 19位
-
代码
#include <bits/stdc++.h> using namespace std; const int N = 2e5 + 10; const int mod = 1e9 + 7; void solve() { string s; int n; cin >> n; cin >> s; int maxx = 0; for (int i = 0; i < s.length(); i++) { maxx = max((int)s[i], maxx); } cout << maxx - 'a' + 1 << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int __ = 1; cin >> __; while (__--) { solve(); } return 0; }
B 题目链接
-
题目大意
给你一个数组a,对于每个a[i],在a数组中找出除了a[i]自己,最大的数,然后输出该数与a[i]的差值
-
思路
求出数组中最大的数(maxx_1)和第二大的数(maxx_2),遍历数组,如果a[i]不是最大的数 就输出a[i]-maxx_1,否则输出a[i]-maxx_2
-
代码
#include <bits/stdc++.h> using namespace std; const int N = 2e5 + 10; const int mod = 1e9 + 7; void solve() { int n; cin >> n; vector<int> vec(n); int maxx = 0; int sec = 0; for (int i = 0; i < n; i++) { cin >> vec[i]; if (vec[i] > maxx) { sec = maxx; maxx = max(vec[i], maxx); } else if (vec[i] > sec) { sec = vec[i]; } } for (int i = 0; i < n; i++) { if (vec[i] != maxx) { cout << vec[i] - maxx << ' '; } else { cout << maxx - sec << ' '; } } cout << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int __ = 1; cin >> __; while (__--) { solve(); } return 0; }
C题目链接
-
题目大意
给定一串数组,问这个数组a[ l .....r ]是否满足如下性质 0 <= l <= r <= n - 1 a l = a l + 1 = a l + 2...... = ar l = 0 or a l - 1 > a l r = n - 1 or a r < a r + 1 若满足这些性质,输出YES 否则输出 NO
-
思路
形成一个山谷我们需要先下降然后上升 我们定义一个flag flag=0 代表 现在是无状态 flag=1 代表 下降状态,如果接下来有一个上升的话就会形成一个山谷 需要注意 初始时 flag为1,结束时还需要判断一下flag是否为1 如果为1,山谷数+1 原因见原题目 具体实现见代码
-
代码
#include <bits/stdc++.h> using namespace std; const int N = 2e5 + 10; const int mod = 1e9 + 7; void solve() { int n; cin >> n; vector<int> vec(n); for (int i = 0; i < n; i++) cin >> vec[i]; int flag = 1; int cnt = 0; for (int i = 1; i < n; i++) { if (vec[i] > vec[i - 1]) //假如现在是上升 并且flag状态为1 ,山谷数+1 { if (flag == 1) { flag = 0; cnt++; } } else if (vec[i] < vec[i - 1]) //如果现在是下降 那么将flag赋值为1 { flag = 1; } } if (flag == 1) cnt++; if (cnt == 1) cout << "YES\n"; else cout << "NO\n"; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int __ = 1; cin >> __; while (__--) { solve(); } return 0; }
D 题目链接
-
题目大意
给定一串二进制数组,把其中一个 1 变成 0 或者 0 变成 1 使得数组逆序对数量最大,问这个最大数量是几
-
思路
先求出不变的情况下 逆序对的个数 ans case1:我们把一个0 变成1 那么这次改变对答案的贡献为 后面所有的0 - 前面所有的1 case2:我们把一个1 变成0 那么这次改变对答案的贡献为 前面所有的1 - 后面所有的0 然后把所有的情况都算出来 得到一个最大值 加到ans上 详情见代码 时间复杂度(O(n))
-
代码
#include <bits/stdc++.h> using namespace std; #define int long long const int N = 2e5 + 10; const int mod = 1e9 + 7; int sum[N]; //sum[i] 代表前i个数有多少个1 void solve() { int n; cin >> n; vector<int> vec(n + 1); for (int i = 1; i <= n; i++) { sum[i] = 0; } for (int i = 1; i <= n; i++) { cin >> vec[i]; sum[i] = sum[i - 1] + vec[i]; } int ans = 0; for (int i = 1; i <= n; i++) //先计算 不变的情况下的答案 { if (vec[i] == 1) { ans += ((n - i) - (sum[n] - sum[i])); } } int maxx = 0; for (int i = 1; i <= n; i++) { if (vec[i] == 0) { maxx = max(maxx, ((n - i) - (sum[n] - sum[i])) - sum[i]); //逻辑 见思路 } else if (vec[i] == 1) { maxx = max(maxx, sum[i - 1] - ((n - i) - (sum[n] - sum[i]))); //逻辑 见思路 } } cout << maxx + ans << '\n'; } signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int __ = 1; cin >> __; while (__--) { solve(); } return 0; }
E 题目链接
-
题目大意
有n个任务。如果你完成第i个任务,你将获得ai币。你每天最多只能完成一个任务。然而,一旦你完成了一个任务,在K天内你不能再做同样的任务。(例如,如果k=2,你在第1天做了任务1,那么你在第2天或第3天不能做,但你可以在第4天再做)。 给你两个整数c和d。找出k的最大值,使你在d天内至少能获得c个硬币。如果不存在这样的k,则输出Impossible。如果k可以是任意大的,则输出Infinity。
-
思路
二分答案 得到数组后先排序 如果最大的a[i]*d < c的话 那么无解 输出 Impossible 如果排序后数组的 前d 个数的和 > c 输出 Infinity 然后进行二分答案 具体的check函数 见代码 需要注意的是 代码中min函数对数组访问越界的控制
-
代码
#include <bits/stdc++.h> using namespace std; #define int long long const int N = 2e5 + 10; const int mod = 1e9 + 7; int vec[N]; int c, d; int n; bool check(int k) { k += 1; int sy = d - (d / k) * k; //进行k轮后剩余的天数 等效于 sy = d % k 也可以 int js = 0; for (int i = 1; i <= min(k, n); i++) { js += vec[i]; } js *= (d / k); for (int i = 1; i <= min(sy, n); i++) { js += vec[i]; } return js >= c; } void solve() { cin >> n >> c >> d; for (int i = 1; i <= n; i++) { cin >> vec[i]; } sort(vec + 1, vec + n + 1, greater<int>()); if (vec[1] * d < c) { cout << "Impossible" << '\n'; return; } else { int ans = 0; for (int i = 1; i <= min(n, d); i++) //不能直接 i<=d 因为d可能比n大 导致访问越界 其他地方的min函数作用亦然 { ans += vec[i]; } if (ans >= c) { cout << "Infinity" << '\n'; return; } else { int anss = 0; int l = 0, r = 1e9 + 10; while (l <= r) { int mid = l + r >> 1; if (check(mid)) { anss = mid; l = mid + 1; } else { r = mid - 1; } } cout << anss << '\n'; } } } signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int __ = 1; cin >> __; while (__--) { solve(); } return 0; }
F题目链接
-
题目大意
给你一棵树和两个点α,b,边有边权。你可以在任意时刻从当前所在的点跳到任意除了b以外的点。求有没有方案使得从a出发,到达b时边权X0r和为0。
-
思路
首先我们确定一个共识 就是一条边不会被走两次 因为重走一条边没有任何意义 x^x=0 并且这是一棵树 是不会出现环的 我们考虑先从b出发做一遍 bfs 在bfs的过程中 我们可以得到很多的 {x,y} x代表当前走到的点 y代表走到这个点的val 我们定义一个 map<int> mp 对于每一个{x,y} 我们让 mp[y]=1; 我们再考虑从a点出发 做一遍bfs 我们会获得很多的 {x1,y1} x1代表当前走到的点 y1代表走到这个点的val。如果mp[y1]=1的话,我们就可以直接飞到一个点 使得最后走到b的异或和为0;
-
代码
#include <bits/stdc++.h> using namespace std; #define int long long const int N = 1e5 + 10; const int mod = 1e9 + 7; vector<pair<int, int>> vec[N]; int vis[N]; void solve() { map<int, int> mp; int n; int a, b; cin >> n >> a >> b; for (int i = 1; i <= n; i++) { vis[i] = 0; vec[i].clear(); } for (int i = 1; i <= n - 1; i++) { int u, v, val; cin >> u >> v >> val; vec[u].push_back({v, val}); vec[v].push_back({u, val}); } queue<pair<int, int>> que; que.push({b, 0}); vis[b] = 1; while (que.size()) { auto u = que.front(); que.pop(); if (u.first != b) mp[u.second] = 1; for (int i = 0; i < vec[u.first].size(); i++) { if (!vis[vec[u.first][i].first]) { vis[vec[u.first][i].first] = 1; que.push({vec[u.first][i].first, vec[u.first][i].second ^ u.second}); } } } for (int i = 1; i <= n; i++) vis[i] = 0; que.push({a, 0}); vis[a] = 1; vis[b] = 1; int flag = 0; while (que.size()) { auto u = que.front(); if (mp[u.second]) { flag = 1; break; } que.pop(); for (int i = 0; i < vec[u.first].size(); i++) { if (!vis[vec[u.first][i].first]) { vis[vec[u.first][i].first] = 1; que.push({vec[u.first][i].first, vec[u.first][i].second ^ u.second}); } } }; if (flag == 1) cout << "YES\n"; else cout << "NO\n"; } signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int __ = 1; cin >> __; while (__--) { solve(); } return 0; }
G题纯签到就不讲了。题解写的有错误还请指正。
标签:maxx,const,int,题解,flag,欢乐,vec,结训,solve From: https://www.cnblogs.com/x1uc/p/17441640.html