2024ICPC沈阳VP
题目
wqz秒了三个,gym切了好几个思路没过,我全程卡在b题坐牢,悲惨的一生。
戏剧性的是gym把k题思路切出来了,而k题正式赛时连jly都没有过。。可能这就是物理竞赛神力吧。
3题铜牌。队友过的题这里也会重新写一下,尽力补完medium。
没写思路的题指路qz哥哥题解,这里主要就是放代码
J
#include <bits/stdc++.h> using namespace std; void solve() { map<int, string>mp1, mp2; for (int i = 1; i <= 4; i++) { int x;string s;cin >> s>> x; mp1[-x] = s; } for (int i = 1; i <= 4; i++) { int x;string s;cin >> s>> x; mp2[-x] = s; } if (mp1.begin()->first < mp2.begin()->first) { cout << mp1.begin()->second << " beats " << mp2.begin()->second; } else { cout << mp2.begin()->second << " beats " << mp1.begin()->second; } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t = 1; // cin >> t; while(t--) { solve(); } }
D
#include <bits/stdc++.h> using namespace std; const int N = 5e5 + 7; using i64 = long long; void solve() { int n; cin >> n; vector<int>a(n + 1), b(n + 1); vector<pair<int, int>> v(n + 1, {0, 0}); int sum = 0; vector<int>vis(n + 1, 0); for (int i = 1; i <= n; i++) cin >> a[i]; for (int i = 1; i <= n; i++) cin >> b[i]; for (int i = 1; i <= n; i++) v[i] = {a[i], b[i]}; sort(v.begin(), v.end()); for (int i = 1; i <= n; i++) { int x = i; if (vis[x]) continue; ++sum; while (!vis[x]) { vis[x] = 1; x = v[x].second; } } int ans = (n % 2 != sum % 2); cout << (ans ? 'A' : 'B'); for (int i = 1; i < n; i++) { char c; int t, l, r; cin >> c >> l >> r >> t; if ((r - l) % 2 == 1 && t % 2 == (r - l) % 2) { ans ^= 1; } cout << (ans ? 'A' : 'B'); } cout << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t = 1; cin >> t; while(t--) { solve(); } }
E
B
M
G
伪装成计算几何的数学题。。
完全想错思路了,求面积却一直想着如何求出正确的多边形长啥样。。
- x坐标没有重复的 (直接问中间的n-2个点即可)
- x坐标有重复的(问分段中点求解)
这里r和s是分数,用long double精度够,还有一个就是发现面积两倍是整数且在2e6范围内,可以乘法逆元自己找质数取模算,非常神奇。
code
```cpp #include <bits/stdc++.h> using namespace std; const int N = 1048576 + 7, mod = 998244353; #define ld long double #define pild pair<int, ld> int n, m, r, s; long double que(int x, int y) { cout <<"? " << x << ' '<< y << endl; long double r, s; cin >> r >> s; return r / s; } void solve() { cin >> n; bool rep = 1; set<int>st; for (int i = 1; i <= n; i++) { int x, y; cin >> x >> y; st.insert(x); } if (st.size() == n) rep = 0; set<int>::iterator it; vector<ld>vt; for (it = st.begin(); it!= st.end(); it++) vt.push_back(*it); ld l1 = 0, l2 = 0; ld ans = 0; if (rep) { for (int i = 1; i < vt.size(); i++) { ans += ((vt[i] - vt[i - 1]) * (que(vt[i] + vt[i - 1], 2))); } } else { for (int i = 1; i < vt.size(); i++) { if (i == vt.size() - 1) { ans += (vt[i] - vt[i - 1]) * (l1)/2; break; } l2 = que(vt[i], 1); ans += ((vt[i] - vt[i - 1]) * (l1 + l2)) / 2; l1 = l2; } } ans *= 2; int a = round(ans); if (a % 2 == 0) cout << "! " << a/2 << ' ' << 1 << endl; else cout << "! " << a << ' ' << 2 << endl; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t = 1; cin >> t; while(t--) { solve(); } } ```
H
最大难点在于读懂题意。
求dfs操作时在完全图中能选的合法子集方案。
观察出以下几点性质:
可连边的点为大于 的子树内点, 若此类点有k个,方案数为- 1所在树大小为n-1时可以不经过特殊边
- 求解答案只需要对所有连接两棵树的方案求和,设连接点为(p,q),1为根的树为T1,另一棵树为T2
- T1内连边方案与p,q无关,dfs序排列后子树是连续的区间,在区间内找出最大v然后转换为二维数点问题
- T2内连边方案是以q为根的方案数与p无关,按dfs序排列后主席树求解
- T1T2之间连边方案在1~p的链上点和T2内点产生与q无关,也就可以直接枚举p然后累计求答案
- 将1,2答案和,3答案和乘起来就是最后答案
贴一个类似使用dfs序+主席树二维数点的题目,感觉也要成为经典思路了。
code
K
等gym大神发题解中
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】