提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
在这个瞬息万变的时代,科技发展日新月异,编程作为一项基础技能,已逐渐成为人们不可或缺的一部分。参加算法练习赛有很多好处,例如提高编程技能、锻炼思维能力、增强自信心等等。
打算法竞赛,要多进行练习,去洛谷,牛客网,蓝桥杯等等网站上多参加练习赛和周赛,实力强可以去Codeforces上练习。话不多说,开始今日份习题讲解。
叮!你有一份习题请查收!
一、前缀和习题
数组段数
1.题目链接
C-数组段数_牛客小白月赛86(重现赛) (nowcoder.com)
2.题目描述
3.题目讲解
首先,拿到本题,我们先理解题意:
小红对小灰灰提出了m个询问,第i个询问给出两个参数L, R,代表小红截取了原数组的的一部分。对于每个询问,小灰灰想知道小红截取出的数组有多少段。其段数被定义为最小的 k 使得将数组划分成连续的 k 段后,每个元素都属于某一段,且每段数组中的元素种类应该全部相同。
简单来说,就是在给出一段数组在查询有多少段,相邻的元素如果相同则为一段,那不是好办嘛,一个for循环,检查时候,计数
加一就好啦,但事情有我们想的那么简单吗?
上代码!
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int a[N];
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
while(m--){
int l,r,cnt=0;
scanf("%d%d",&l,&r);
for(int i=l;i<r;i++){
if(a[i]!=a[i+1]) cnt++;
}
printf("%d\n",cnt+1);
}
return 0;
}
样例加入,没毛病,提交!不出意外,超时了!!!
那我们怎么思考呢?在区间进行操作,这不是我前几天蓝桥杯真题所运用的前缀和思想!(详见每日算法题-蓝桥杯真题-CSDN博客)和(基本算法-前缀和 模板+习题-CSDN博客)
那在本题怎么使用呢?
发现相同时不累加,不相同累加,那么假定代表前缀和数组,查询数组区间有几段,不就是就区间的前缀和嘛!
欧克了,那怎么构造前缀和公式呢?重点在这一句:相同时不累加,不相同累加,则可得到:
那么区间内前缀和则为:,还有一个小点我们要考虑到,假设区间外的数和查询区间的第一个重复那么要多加一个1,因此求区间前缀和为:
最后,就是上代码环节,虽然有人就看这个(狗头保护)
4.完整代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
long long a[N],s[N];
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) {
scanf("%lld",&a[i]);
s[i]=s[i-1]+(a[i]!=a[i-1]);
}
while(m--){
int l,r,cnt=0;
scanf("%d%d",&l,&r);
printf("%lld\n",s[r]-s[l-1]+(a[l]==a[l-1]));
}
return 0;
}
二、模拟习题
乘飞机【算法赛】
1.题目链接
4.乘飞机【算法赛】 - 蓝桥云课 (lanqiao.cn)
2.题目描述
3.题目讲解
本题题意:在给定区间中是否存在两个数相差小于或者365,那按照题意模拟即可。
我用的是暴力法,根据题意,两层for循环,加判断,判断条件
即可(本题测试数据比较水,暴力即可通过,其实很莫名其妙,才开始不通过,然后有修改了一点点过了,哈哈哈)
还有一种方法是,当区间之差大于100,一定是YES,小于100时暴力,这样如果数据量大,不会超时,但为什么大于100,就一定是YES,鸽笼原理,36500/100=365,在大于100,一定有插值小于或者等于365(因为已经全部枚举过了,举一个例子更好理解,任意 367 个人中至少有 2 人生日(出生的月和日)相同。)
4.完整代码
(1)暴力
#include <iostream>
using namespace std;
const int N=1e5+10;
int a[N];
int main()
{
int n,m,cnt=0;
cin>>n>>m;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
while(m--){
int x,y,cnt=0;
scanf("%d%d",&x,&y);
for(int i=x;i<=y-1;i++){
for(int j=i+1;j<=y;j++){
int z=abs(a[i]-a[j]);
if(z<=365) {
cnt=1;
printf("YES\n");
break;
}
}
if(cnt) break;
}
if(!cnt) printf("NO\n");
}
return 0;
}
(2) 鸽笼原理
#include <iostream>
using namespace std;
const int N=1e5+10;
int a[N];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
while(m--){
int x,y,cnt=0;
scanf("%d%d",&x,&y);
if(y-x>100) cout<<"YES"<<endl;
else{
for(int i=x;i<=y-1;i++){
for(int j=i+1;j<=y;j++){
int z=abs(a[j]-a[i]);
if(z<=365) cnt=1;
if(cnt==1) break;
else continue;
}
}
if(cnt==1) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
return 0;
}
总结
结束了!!!
看完了?可以给作者一个赞和收藏,嘿嘿,要不顺手点个关注?希望能和友友们交流,以及欢迎友友们评论!
这是这周参加了两场算法比赛,分别是蓝桥小白,和牛客网小白比赛,蓝桥ac4道,牛客ac3道,下周进行搜索专题学习,牛客网第四道是连通块的题,好久之前看的,已经不会敲了,下周继续努力!!!
本周博客总结:
感兴趣的小伙伴可以去看一看哦。