其他分享
首页 > 其他分享> > 第一次训练赛解题报告

第一次训练赛解题报告

作者:互联网

我训练赛中做出4题, 赛后补4题, 最终使用word完成解题报告, 报告上呈现出9题.

补题数量: 8/ 10.

收获感悟:这次训练赛是对我们从寒假开始上的课的一个总结,感觉自己学的一点都不扎实,前缀和差分的知识很简单,但是一遇到具体题目结合起来就令我显得十分吃力,自己基础不牢,做题总是在乎做题量,做出的题目没有分类总结,做不出来的题目也没有去反思总结,想的很多,行动起来却十分吃力,还是需要多刷题,要是能有一个基础算法的刷题网站就好了,还要继续努力,希望自己不要被acm扫地出门,在这个大家庭学习非常快乐,卑微.jpg

我会更着学长好好学习算法的,希望自己能对一些非常长的题目静下心来分析,用心学习,不能三心二意。

通过这次训练赛,加强了我对前缀和和差分以及二分算法等一些基础算法的认识,认识到了自己与其他人的差距,在接下来的训练我会继续努力听讲学习算法知识。

A:幸运数字们https://vjudge.csgrandeur.cn/problem/51Nod-2091

思路:暴力循环,对每一个区间内的数进行取余10后除以10,直到区间内的数的位数中有7输出这个数,并停止循环。

考察内容:循环

#include<bits/stdc++.h>
using namespace std;
int main()
{
int l,r;
scanf("%d%d",&l,&r);
int flag=0;
for(int i=l;i<=r;i++)
{
   int x=i;
   while(x!=0)
   {
    if(x%10==7)
    {
    printf("%d\n",i);
    flag=1;
    break;
}
x=x/10;
   }
}
if(flag==0)
{
printf("None\n");
}
return 0;
}

B:二分查找(5)

https://vjudge.csgrandeur.cn/problem/%E8%AE%A1%E8%92%9C%E5%AE%A2-T1555

二分模板题

#include<bits/stdc++.h>
using namespace std;
int a[1000000];
int main()
{
int n,m;
scanf("%d%d",&n,&m);//为什么要注释??
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n);
while(m--)
{
int x;
scanf("%d",&x);
if(x<a[0])
{
printf("-1\n");
continue;
    }
    if(x>=a[n-1])
    {
     printf("%d\n",a[n-1]);
     continue;
}
int l=0,r=n-1;
while(l<r)
{
int mid=(r+l+1)/2;
if(a[mid]<=x)
{
l=mid;
    }
else
r=mid-1;
 }
 cout<<a[l]<<endl;
}
return 0;
}

C(补): 海巴莱堆叠

https://vjudge.csgrandeur.cn/problem/SPOJ-HAYBALE

考察内容:差分,前缀和

思路:通过差分给输入的区间直接加上一包干草堆,再求差分数数组的前缀和,排序,因为n是奇数,直接取中位数即可。

反思:看到这么长的英文题就怕,直接放弃了,太长了,看的我发慌,希望改掉这个毛病。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1000005;
int w[N],a[N];
int main()
{
    int n,k,x,y;
scanf("%d%d",&n,&k);
while(k--)
{
scanf("%d%d",&x,&y);
w[x]++;
w[y+1]--;
}
for(int i=1;i<=n;++i)
a[i]=a[i-1]+w[i];
sort(a+1,a+n+1);
printf("%d",a[n/2+1]);
return 0;
}

D:最大子阵列

https://vjudge.csgrandeur.cn/problem/%E8%AE%A1%E8%92%9C%E5%AE%A2-21

考察内容:双指针,数据较少,暴力也行。

思路:暴力,定义一个指针j往下移,对每个值加上于上一个值对比,如果大于则替换。直到遍历完所有数就输出最大的值。

#include<bits/stdc++.h>
using namespace std;
int a[1010];
int main()
{
int n;
scanf("%d",&n);
int sum1=0,sum=0;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
sum=a[0];
for(int i=0;i<n;i++)
{
sum1=0;
for(int j=i;j<n;j++)
{
sum1+=a[j];
if(sum1>sum)
sum=sum1;
    }
}
printf("%d\n",sum);
return 0;
}

E:激光炸弹

https://vjudge.csgrandeur.cn/problem/%E8%AE%A1%E8%92%9C%E5%AE%A2-T2431

考察内容:二维数组的前缀和

思路:定义一个二维数组a,对于输入的x,y每次于R比较用来确定正方形的边界,二维前缀和运算,枚举边长为R的正方形右下角坐标(i,j),求其在正方形内所有价值之和,再更新答案。

#include<bits/stdc++.h>
using namespace std;
const int N=5010;
int a[N][N];
int main()
{
int N,R;
scanf("%d%d",&N,&R);
int n=R,m=R;
while(N--)
{
int x,y,v;
scanf("%d%d%d",&x,&y,&v);
x++,y++;
n=max(n,x);
m=max(m,y);
a[x][y]+=v;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
}
}
int sum=0;
for(int i=R;i<=n;i++)
{
for(int j=R;j<=m;j++)
{
sum=max(sum,a[i][j]-a[i-R][j]-a[i][j-R]+a[i-R][j-R]);
}
}
printf("%d\n",sum);
return 0;
}

F(补):Hate "A"

https://vjudge.csgrandeur.cn/problem/CodeForces-1146B

思路:网上看的,遍历str字符串,将其分为两个字符串,一个是不加a的字符串suf,另外一个是加了字符串的pre,边加边判断其总长度是不是等于原串长度,直到循环结束的时候如果没有得出结果就输出":("。

#include<bits/stdc++.h>
using namespace std;
int main(){
string str,pre,suf;
cin >> str;
for(auto c : str){
pre += c;
if(c != 'a') suf += c;
if(pre.size() + suf.size() == str.size() && pre + suf == str){
cout << pre << endl;
return 0;
}
} 
cout << ":(" << endl;
return 0;
}

I(补):非常男女

https://vjudge.csgrandeur.cn/problem/%E8%AE%A1%E8%92%9C%E5%AE%A2-T1853

考察内容:前缀和,双指针。

思路:定义女生为-1,男生为1,定义数组S为per数组的前缀和,只要找到两个位置的前缀和相等,他们之间就是男女相等的连续子序列。我们记录每个前缀和第一次出现的位置,下次出现的时候,减去第一次的位置就是长度。

#include <iostream>
using namespace std;
const int N=1e5+10;
int per[N],s[N];
int main(){
    int n,i,j,max=0;
    cin>>n;
    for(i=1;i<=n;i++){
        scanf("%d",&per[i]);
        if(per[i]==0) per[i]=-1;
        s[i]=s[i-1]+per[i];
    }
    for(i=1;i<=n;i++){
        for(j=0;j<i;j++){
            if(s[i]==s[j]){
                if(i-j>max)
                    max=i-j;
                break;
            }
        }
    }
    cout<<max;
    return 0;
}

H(补):铺设道路

https://vjudge.csgrandeur.cn/problem/%E8%AE%A1%E8%92%9C%E5%AE%A2-T2050

考察内容:贪心算法

 思路:遍历道路数组:如果前一个块比后一块小,那么计数器加上其差值,因为这样做,第一个坑设置为坑的深度-0,当一个坑比前一个坑深时,需要相对于已经储存的次数的额外操作次数就是其差值.

#include<iostream>
#include<cstdio>
using namespace std;
int n,ans=0,l=0;
int main()
{
    scanf("%d",&n);
    for(int a=1;a<=n;a++)
    {
        int p;
        scanf("%d",&p);//当前深度
        if(p>l)//如果当前深度大于前一段深度
        {
            ans=ans+p-l;//总步数加当前深度减前一段深度
        }
        l=p;//前一段深度;
    }
    printf("%d\n",ans);
}

标签:E8%,前缀,int,第一次,解题,训练赛,AE%,include,cn
来源: https://blog.csdn.net/qq_62122039/article/details/122590586