2020-03-28 纪中六年级A组比赛

第一题

1287. 小X与队列 (queue)
题目描述
  小X正和同学们做列队的练习。
  有n名同学排成一路纵队,编号为i的同学排在从前往后数第i个位置上,即:初始时的队列为1, 2, 3, ..., n。
  接下来小X会发出若干条指令,每条指令形如“请编号为x的同学排到最前面来”。(例如:若当前时刻的队列为5, 4, 3, 2, 1,发出一条x=2的指令后,队列变成了2, 5, 4, 3, 1。)
  小X发出了很多很多指令,同学们晕头转向不知道该怎么排列。于是就请你算一算,执行完这些指令后,队列应该变成什么样?

输入
第一行两个用空格隔开的正整数n和m,分别表示人数和指令数。
第二行m个用空格隔开的正整数x[i],按顺序表示每次指令的x值。

输出
输出仅有一行包含n个正整数,相邻两个数之间用一个空格隔开,表示执行完所有指令后的队列。

样例输入
4 3
2 3 2

样例输出
2 3 1 4

数据范围限制
对于30%的数据,1<=n,m<=1000
对于另外30%的数据,n=m,且1~n每个数在x[i]中恰好出现一次。
对于100%的数据,1<=n,m<=100000

提示
样例解释
  第一条指令前:1 2 3 4
  第一条指令后(x=2)2 1 3 4
  第二条指令后(x=3)3 2 1 4
  第三条指令后(x=2)2 3 1 4
思路

这题其实非常简单,输入后,从m~1循环。用一个b数组来存第a[i]这个编号的小伙伴是否已经拉到了最前面。然后就在循环里判断如果b[a[i]]没有拉到前面,如果没有我们就用c数组存下a[i]的值,把b[a[i]]的值改为已经拉到了最前面。

核心代码
for(int i=m;i>=1;i--)
	{
		if(b[a[i]]==0)
		{
			c[k++]=a[i];     
			b[a[i]]=1;
		}
	}
	for(int i=0;i<k;i++)
		printf("%d ",c[i]);
	for(int i=1;i<=n;i++)
		if(b[i]==0)printf("%d ",i);
代码信息
时间复杂度总时间
Θ(n)3m+n

第二题

1397. 小幸福(e)
题目描述
有n个小朋友,他们商量在保证作业做完的前提下出去玩。第i个小朋友的可以玩耍时间为Si~Ti。这里Si~Ti表示的是时间段,比如Si=2,Ti=4,那么意味着这位小朋友在时刻1不能玩,时刻234可以去玩,时刻4以后都不能出去玩。如果在某个时刻,在一起玩的小朋友个数不少K个,那么这一时刻就是幸福的。现在你要求出所有幸福的时刻长度。

输入
三行 第一行:n k  (n个小朋友,一起玩的小朋友达到k个为幸福)
第二行:S1 S2 ... Sn
第三行:T1 T2 ... Tn

输出
一行:幸福时刻的长度

样例输入
4 3
1 2 2 4
5 2 4 6

样例输出
2

数据范围限制
50% n<=1000 1<=Si<=Ti<=1000
100% n<=100000 1<=Si<=Ti<=1000000000

提示
时刻               1      2    3     4   5  6
第一个小朋友玩耍时间:X     X    X    X   X
第二个小朋友玩耍时间:       X
第三个小朋友玩耍时间:       X    X    X
第四个小朋友玩耍时间:                    X   X  X
第2分钟和第4分钟一起玩耍的小朋友达到了3个所以是幸福的时刻,幸福时刻长度为2
思路

这一题要定义一个二维数组a[i][0]用来存时刻,a[i][1]用来存是是开始还是结束,进去赋值为1,出来赋值为-1。注意:结束时刻要加一。然后把整个数组一起排序,循环i~n*2,一次用来循环同一个时间点的刻度,算完这个时刻剩多少人后判断是否大于k。把ans加上a[j][0]-a[i][0]就行了。最后i=j。

核心代码
int i=1,s=0,ans=0,now=0;bool w=false;
while(i<=n*2)
{
	int j=i;
	while(a[j][0]==a[i][0])
	{
		s=s+a[j][1];
		j++;
	}
	if(s>=k)
		ans=ans+a[j][0]-a[i][0]; 
	i=j;
}
代码信息
时间复杂度总时间
Θ(n*log(n))3n+n*log(n)

第三题

1392. 下落的小球(five)
题目描述
有一棵满二叉树,最大深度为D,且所有叶子的深度都相同。所有结点从上到下从左到右编号为123...2^D-1。在结点1处放一个小球,它会往下落。每个内结点上都有一个开关,初始全部关闭,当每次有小球落到一个开关上时,它的状态都会改变。当小球到达一个内结点时,如果该结点上的开关关闭,则往左走,否者往右走,直到走到叶子结点。
一些小球从结点1处依次开始下落,最后一个小球将会落到哪里呢?

输入
输入文件five.in
只有一行共有二个正整数:d k   (其中d为叶子深度,k为小球个数,1 <= k <= 2^(d-1) )

输出
输出文件five.out
只有一行且只有一个正整数:第k个小球最后所在的叶子编号

样例输入
16 12345

样例输出
36358

数据范围限制
50% 的数据: 1 <= d <= 40  
80% 的数据: 1 <= d <= 60  
100% 的数据: 1 <= d <= 100 
思路

这道题其实也不算难,只是高精度乘除分。 首先,我们了解一下上面那个链接,然后再推一下满二叉树的特性:
(1)二叉树是n个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树组成。下图展示了一棵普通二叉树,根节点是A,其中G、I、J、F成为叶子节点。
在这里插入图片描述
(2)满二叉树:在一棵二叉树中。如果所有分支结点都存在左子树和右子树,并且所有叶子结点都在同一层上,这样的二叉树称为满二叉树。
满二叉树的特点有:
1)叶子只能出现在最下一层。出现在其它层就不可能达成平衡。
2)非叶子结点的度一定是2,即他们的下一层都有两个结点。
3)在同样深度的二叉树中,满二叉树的结点个数最多,叶子数最多。
在这里插入图片描述

(3)二叉树的顺序存储结构就是使用一维数组存储二叉树中的结点,并且结点的存储位置,就是数组的下标索引。
在这里插入图片描述
在这里插入图片描述
对于每一个球,我们都能推出他应该向左还是向右,所以利用4),我们就能得到其最后球最后在哪个结点。

核心代码
while(f>='0'&&f<='9')
	{
        k[0]+=1;
        k[k[0]]=f-'0';
        f=getchar();
    }
    a[0]=1;
    a[1]=1;
    for(int i=1;i<d;i++)
	{
        for(int j=1;j<=a[0];j++)
            a[j]*=2;
        for(int j=1;j<=a[0]+1;j++)
		{
            a[j+1]+=a[j]/10;
            a[j]=a[j]%10;
        }
        if(k[k[0]]%2==0)
		{
            a[1]++;
            for(int j=1;j<=a[0];j++)
			{
                a[j+1]+=a[j]/10;
                a[j]=a[j]%10;
            }
        }
        if(a[a[0]+1]!=0)
            a[0]++;
        int bj=0;
        if(k[k[0]]%2==1)k[k[0]]+=1;
        for(int j=js;j<=k[0];j++)
		{
            k[j+1]+=k[j]%2*10;
            if(k[j]/2!=0||bj==1)
			{
                k[j]=k[j]/2;
                bj=1;
            }
            else if(bj==0)js++;;
        }
    }
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值