【牛客训练记录】牛客周赛 Round 66
训练情况
赛后反思
目测 D、E是什么神秘线段树数据结构题吧,没有做出来,还得加练。
A题
先三个数排序,要么那最大的,要么拿两个较小的和,答案取大值即可。
#include <bits/stdc++.h>
#define int long long
using 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 long
using 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 long
using 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 long
using 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;
}