A~D题解
前言:本人不是大佬,解法不一定是最优解,面向刚入门的朋友。若有错误,敬请指正!
A:小苯吃糖果
输出 三个数里的 最大值 或者 更小的那两个数的和,取他们的最大值即可
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAX=1e9+7;
int t,n,m,s;
int a[5];
void solve(){
for(int i=0;i<3;i++)
cin>>a[i];
sort(a,a+3);
if(a[2]<a[1]+a[0])
cout<<a[0]+a[1];
else
cout<<a[2];
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
t=1;
//cin>>t;
while(t--){
solve();
}
return 0;
}
B:小苯的排列构造
构造题(constructive algorithms)
构造一个长度为 n 的排列 p,使得这个排列构成的数组 a 不是递增的,其中 ai = pi + p(pi)。也就是数组 a 的第 i 个数 = 排列 p 的第 i 个数 + 排列 p 的第 pi 个数,保证数组 a 不是递增的。我们用样例的排列来找找思路(把下标也写出来,从1开始),圈出每个 ai 对应的 pi、p(pi),找了几个 ai 我们假设如果 ai 对应的两个数是从排列的一首一尾,从两边往中间缩,那有可能满足题意吗?相信数学小王子的你很快就会发现规律,既然 a 不是递增的就行,那构造 所有 ai 都相等就可以了,所以答案可以是逆序的 n。
位于比赛前排的构造题一般不会很难,不要陷入了题目陷阱,思维开阔一点,这种诈骗题算是比较常见的,想要一眼得出答案,需要我们大量的练习。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAX=1e9+7;
int t,n,m,s;
void solve(){
cin>>n;
for(int i=0;i<n;i++)
cout<<n-i<<" ";
cout<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
t=1;
cin>>t;
while(t--){
solve();
}
return 0;
}
c:小苯的最小整数
相信大家都能理解题意,这种要对一个整数操作的题,我们一般都是把整数看成 string 类型,因为整形不好分割每一个数位;我们再看数据范围,1≤n≤10 ^ 10,n最多有10个0(看指数)也就是说 string 类型最多也才 11 位,测试用例 T 最大 10 ^ 5 乘于 10,最多也才 10 ^ 6,那我们就可以放心暴力了。
题目要求尽量小的 n,这可以转换成尽量小的字典序。
什么是字典序呢?就是字符按照ASCLL码表中对应的十进制数的大小的标准来规定字符的大小,从而得出一个字符串的字典序。例如 abb > aab 因为第二个位置 b > a(从左往右开始比较);ab > a。
具体思路请看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAX=1e9+7;
int t,n,m,s;
void solve(){
string s;
cin>>s;
string mi=s,a=s,b=s;
n=s.size();
for(int i=0;i<n-1;i++)
{
char ch=a[0];
string temp=a.substr(1,n-1);//这个函数是获取字符串a中从下标1开始,长度为n-1的字符串
temp+=ch;
if(temp<mi)mi=temp;
a=temp;
}
cout<<mi<<"\n";
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
t=1;
cin>>t;
while(t--){
solve();
}
return 0;
}
D:小苯的蓄水池(easy)
不是并查集,不知道这题怎么用并查集,写的暴力
写题解好累,具体思路看代码吧,写了比较详细的注释(easy版本 n 才2000,完全可以暴力的)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define int long long
int t,n,m;
int a[10004];
int sum[10004];//前缀和
int sign[10003][3];//用来存第i个水池能够连通的 最左边sign[i][0] 以及 最右边sign[i][1] 的水池位置
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum[i]=sum[i-1]+a[i];//前缀和
sign[i][0]=sign[i][1]=i;//开始时每个水池都没有连通其他水池,计为 i
}
while(m--)
{
int op;
cin>>op;
if(op==1)
{
int l,r;
cin>>l>>r;
int lmin=l,rmax=r;//能连通的 最左端 以及 最右端
for(int i=l;i<=r;i++)//找找这个区间有没有更大的范围
{
lmin=min(sign[i][0],lmin);//最左端取min
rmax=max(sign[i][1],rmax);//最右端取max
}
for(int i=lmin;i<=rmax;i++)//lmin ~ rmax的区间的水池都要记录
sign[i][0]=lmin,sign[i][1]=rmax;//记录它们能连通的左右两端的最大范围
}
else
{
int index;
cin>>index;
LL res=sum[sign[index][1]]-sum[sign[index][0]-1];//求区间和
double len=sign[index][1]-sign[index][0]+1;//求长度
printf("%.10f\n",1.0*res/len);
}
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
t=1;
//cin>>t;
while(t--){
solve();
}
return 0;
}
E~G:嘎嘎嘎,不会啊┭┮﹏┭┮
如果对你有帮助可以给我点个赞吗,如果有疑问可以私信我或者评论区提出来!