训练情况
赛后反思
目测 D、E是什么神秘线段树数据结构题吧,没有做出来,还得加练。
A题
先三个数排序,要么那最大的,要么拿两个较小的和,答案取大值即可。
#include <bits/stdc++.h>
#define int long longusing namespace std;void solve(){int a[3];cin>>a[0]>>a[1]>>a[2];sort(a,a+3);cout<<max(a[2],a[0]+a[1]);
}signed main(){// int T; cin>>T; while(T--)solve();return 0;
}
B题
构造 \(p_i + p_{p_i}\) 数组单调不增,那我们就直接考虑给它搞成一样的就行,我们考虑构造一个 \(n\) 到 \(1\) 即可,这样每一位都是 \(n+1\),满足题目条件,所以我们直接 for 循环,输出从 \(n\) 到 \(1\) 即可。
#include <bits/stdc++.h>
#define int long longusing namespace std;void solve(){int n; cin>>n;for(int i = n;i;i--) cout<<i<<" ";cout<<endl;
}signed main(){int T; cin>>T; while(T--)solve();return 0;
}
C题
每次把最前面的一位移动到最后面去,所以我们直接字符串读入,直接全部模拟一遍,全部换一遍答案取最小值即可。
#include <bits/stdc++.h>
#define int long longusing namespace std;int ti(string s){int ans = 0;for(int i = 0;i<s.size();i++){ans = ans * 10 + s[i] - '0';}return ans;
}void solve(){string s; cin>>s;int ans = LONG_LONG_MAX;for(int i = 0;i<s.size();i++){ans = min(ans,ti(s));s += s[0];s.erase(s.begin());}cout<<ans<<endl;
}signed main(){int T; cin>>T; while(T--)solve();return 0;
}
D题
对于维护水池之间的联通,我们考虑使用 DSU(并查集)进行合并操作,对于每次查询遍历一遍更新答案,对于同一个并查集祖先的求个和,还有出现次数,最后算出平均值再赋值回去即可,不知道为什么WA了两个点。
#include <bits/stdc++.h>
#define int long longusing namespace std;const int N = 2e3 + 3;int n,m;
double a[N];
int fa[N];
double sum[N];
int cnt[N];int Find(int x){if(fa[x] == x) return x;return fa[x] = Find(fa[x]);
}void Union(int x,int y){x = Find(x); y = Find(y);if(x == y) return;fa[y] = x;
}void solve(){cin>>n>>m;for(int i = 1;i<=n;i++) fa[i] = i;for(int i = 1;i<=n;i++) cin>>a[i];while(m--){int opt; cin>>opt;if(opt == 1){int l,r; cin>>l>>r;for(int i = l;i<r;i++) Union(i,i+1);} else if(opt == 2){int x; cin>>x;for(int i = 1;i<=n;i++) sum[i] = 0,cnt[i]= 0;for(int i = 1;i<=n;i++) sum[Find(i)] += a[i],cnt[Find(i)]++;for(int i = 1;i<=n;i++){a[i] = sum[Find(i)] / cnt[Find(i)];}printf("%.10lf\n",a[x]);}}
}signed main(){// int T; cin>>T; while(T--)solve();return 0;
}