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

伪装成计算几何的数学题。。
完全想错思路了,求面积却一直想着如何求出正确的多边形长啥样。。
f(x) 表示对应x的询问结果,发现是线性分段函数,积分可得面积,分为两种情况讨论。

  1. x坐标没有重复的 (直接问中间的n-2个点即可)
  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操作时在完全图中能选的合法子集方案。
观察出以下几点性质:

  1. u 可连边的点为大于vmax 的子树内点, 若此类点有k个,方案数为 2k
  2. 1所在树大小为n-1时可以不经过特殊边
  3. 求解答案只需要对所有连接两棵树的方案求和,设连接点为(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大神发题解中

posted @   lyrrr  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示