开始: 2022-05-29 19:00:00

2022年5月双周赛3(初级班)

结束: 2022-05-29 21:30:00
当前: 2025-06-15 20:53:34  类型:OI 状态:已经结束 

A.最长连号

#include<bits/stdc++.h>
using namespace std;
int n,a[100010],s=1,maxx=1;
//s表示到目前为止连号的长度
//s和maxx一定初始化为1,因为一个数也是连号
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=2; i<=n; i++)
{
if(a[i]-a[i-1]==1) s++;//如果这一个数和前一个数是连号,s++
else s=1;//否则,连号要重新开始计数,s等于1
if(s>maxx) maxx=s;//和最大值比大小
}
cout<<maxx;//输出最大值
return 0;
}
//总结:很多同学会做这道题,但读题不仔细,数组开小了,应该避免犯这样的错误
//这道题n的范围是1~100000,我们开数组时应该适当比n的最大值多开一点,如100010
//注意,当数组比较大的时候,不要定义在函数内,应该定义为全局变量

B. 校门外的树

#include<bits/stdc++.h>
using namespace std;
int L,M;
int cnt=0;
//剩余树的数目
int vis[10010];
//用来判断树没有被访问过
int main()
{
cin>>L>>M;
for(int i=1;i<=M;i++)
{
int head,tail;//定义区间的头和尾
cin>>head>>tail;
for(int j=head;j<=tail;j++) vis[j]=1;//从这个区间的头和尾开始,将所有区间内的树标记为访问过
}
for(int i=0;i<=L;i++)
{
if(vis[i]==0)
cnt++;//计算未被访问过的树的数目
}
cout<<cnt<<endl;
return 0;
}
/*
思路:三遍循环
第一遍,将路上的所有树打上标记0,表示这个点没有被访问过。
注意,第一遍循环可以省略,因为定义为全局变量的数组初始值为0.
第二遍,读入区间的头和尾,从这个区间的头开始循环,到尾结束,标记为1,表示访问过。
第三遍,顺序访问路上的树,只要没访问过,计数加1,这样就求出了路上所有还存在的树的数目。
同学们常见的错误是没有考虑区间重叠的情况。
*/

D. Cantor 表

#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
int x=0;//n在第x行
while(n>0)//n<=0时停止循环
{
x++;
n-=x;
}
n+=x;//减去它之前n的值就是n是该行第几个数,所以要加上它
if(x%2==0) cout<<n<<"/"<<x-n+1;//偶数行
else cout<<x-n+1<<"/"<<n;
return 0;
}
/*
思路:
此题为Z字形编号,不妨将Z形转变为矩阵,方便我们观察。
先是找规律:
1/1(第一行)
1/2 2/1(第二行)
3/1 2/2 1/3(第三行)
1/4 2/3 3/2 4/1(第四行)
注意到每行的第一个数以及后面数的变化方式与层数奇偶是有关系的:
设当前在第x行
1. 如果是奇数行,那么第一个数为x/1,后面的数依次为x-1/2, x-2/3...
2. 如果是偶数行,那么第一个数位1/x,后面的数依次为2/x-1, 3/x-2...
找到规律后,我们要做的就是判断n在第几行,以及n是该行第几个数。
判断n在第几行可以用数学方法,也可以直接循环,用n减去1,再减去2,以此类推。
直到n<=0循环停止,让n<=0的值就是行数,在减去它之前n的值就是n是该行第几个数。
其他找规律的方法还有很多种,只要思路正确,均可解决这道题。
*/