Codeforces Round 967 (Div. 2)
1.Codeforces Round 958 (Div. 2)2.Codeforces Round 957 (Div. 3)3.Codeforces Round 959 sponsored by NEAR (Div. 1 + Div. 2)4.Codeforces Round 960 (Div. 2)5.AtCoder Beginner Contest 3636.Codeforces Round 961 (Div. 2)7.AtCoder Beginner Contest 3628.Codeforces Round 962 (Div. 3)9.Pinely Round 4 (Div. 1 + Div. 2)10.Educational Codeforces Round 168 (Rated for Div. 2)11.AtCoder Beginner Contest 367
12.Codeforces Round 967 (Div. 2)
13.Codeforces Round 968 (Div. 2)14.Educational Codeforces Round 173 (Rated for Div. 2)15.Educational Codeforces Round 172 (Rated for Div. 2)(C-D)16.Codeforces Round 998 (Div. 3)17.2025牛客寒假算法基础集训营218.2025牛客寒假算法基础集训营1题目链接:Codeforces Round 967 (Div. 2) - Codeforces
总结:B题没测试就交wa一发,C题一直没想到怎么回溯,哎。
A. Make All Equal
tag:签到
Solution:找到相同元素的最大值,将其它所有元素删去。
void solve(){ cin >> n; vector<int> a(n); map<int, int> mp; int ans = 0; for (int i = 0; i < n; i ++){ cin >> a[i]; mp[a[i]] ++; ans = max(ans, mp[a[i]]); } cout << n - ans << endl; }
B. Generate Permutation
tag:构造
Solution:对于一个数
Competing:一下就猜中了,写完代码后没测试,wa一发。
void solve(){ cin >> n; if (n % 2 == 0){ cout << "-1\n"; } else{ vector<int> a(n); int t = n - 1; for (int i = 1; t; i ++){ a[i] = t; t -= 2; } t = n; for (int i = n; t >= 1; i --){ a[i] = t; t -= 2; } for (int i = 1; i <= n; i ++){ cout << a[i] << " \n"[i == n]; } } }
C. Guess The Tree
tag:交互 + dfs
Description:给定一个? a b
,会返回一个节点|d(x - a) - d(x - b)|
最小。d(x, a)
最小的节点。用最多
Solution:分析每次询问得到的结果发现每次都会给出
- 需要记录每个节点的父节点,避免重复询问。
- 对于一棵树,我们可以假设任意一个节点为根
Competing:想到应该用
int query(int a, int b){ cout << "? " << a << " " << b << endl; int x; cin >> x; return x; } void dfs(int a, int b){ // a是父节点 if (fa[a] && fa[b]) return; int t = query(a, b); if (a == t || t == b){ fa[b] = a; ans.push_back({a, b}); return; } else{ dfs(a, t); dfs(t, b); } } void solve(){ cin >> n; ans.clear(); for (int i = 0; i <= n; i ++){ fa[i] = 0; } fa[1] = 1; while (ans.size() < n - 1){ for (int i = 2; i <= n; i ++){ if (fa[i] == 0){ dfs(1, i); } } } cout << "! "; for (int i = 0; i < ans.size(); i ++){ cout << ans[i].fi << " " << ans[i].se << " "; } cout << endl; }
D. Longest Max Min Subsequence
tag:思维 + 贪心 + 单调队列优化
Description:给定一个整数序列
n <= 3e5
Solution:我们首先可以确定哪些值是必须要选的。我们要保证能选出最长的序列,就需要记录每个值最后出现的位置,在最后出现的位置最小的元素之前我们可以任意选择,而不能先选在该元素之后的其他元素。
- 一个可选的区间内,对于奇数位我们选择值最大的元素,对于偶数位我们选择值最小的元素。如果我们每次暴力寻找,时间复杂度为
,考虑使用单调队列优化。
void solve(){ cin >> n; vector<int> a(n + 1); unordered_map<int, int> mp; set<int> st; for (int i = 1; i <= n; i ++){ cin >> a[i]; mp[a[i]] = i; } for (auto [x, y] : mp){ // 记录每个元素最后出现的位置 st.insert(y); } int sz = mp.size(); cout << sz << endl; int s = 1; int c = 0; priority_queue<pii, vector<pii>, greater<pii>> smi; // 值从小到大,序号从小到大 priority_queue<pii, vector<pii>, greater<pii>> sma; // 值从大到下,序号从小到大 int tt = 0; while (c < sz){ int et = *(st.begin()); // 当前最前面最后出现的元素的位置 int res, idx; for (int i = s; i <= et; i ++){ if (mp[a[i]] != 0){ // 等于0说明选过了 smi.push({a[i], i}); sma.push({-a[i], i}); } } if ((c + 1) & 1){ // 选最大值 auto [x, y] = sma.top(); res = x, idx = y; } else{ // 选最小值 auto [x, y] = smi.top(); res = x, idx = y; } cout << a[idx] << " "; st.erase(mp[a[idx]]); // 删除选择点的下标 mp[a[idx]] = 0; s = et + 1; c ++; while (sma.size()){ // 删除选择过的元素或者下标小于当前值的元素 auto [x, y] = sma.top(); if (res > 0) res = -res; if (!mp[-x] || y <= idx) sma.pop(); else break; } while (smi.size()){ auto [x, y] = smi.top(); if (res < 0) res = -res; if (!mp[x] || y <= idx) smi.pop(); else break; } } cout << endl; }
合集:
题解
标签:
Codeforces
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!