2022天梯赛

L1-8 静静的推荐 (20 分)

天梯赛结束后,某企业的人力资源部希望组委会能推荐一批优秀的学生,这个整理推荐名单的任务就由静静姐负责。企业接受推荐的流程是这样的:
只考虑得分不低于 175 分的学生;
一共接受 K 批次的推荐名单;
同一批推荐名单上的学生的成绩原则上应严格递增;
如果有的学生天梯赛成绩虽然与前一个人相同,但其参加过 PAT 考试,且成绩达到了该企业的面试分数线,则也可以接受。
给定全体参赛学生的成绩和他们的 PAT 考试成绩,请你帮静静姐算一算,她最多能向企业推荐多少学生?
输入格式:
输入第一行给出 3 个正整数:N(≤105)为参赛学生人数,K(≤5×103)为企业接受的推荐批次,S(≤100)为该企业的 PAT 面试分数线。
随后 N 行,每行给出两个分数,依次为一位学生的天梯赛分数(最高分 290)和 PAT 分数(最高分 100)。
输出格式:
在一行中输出静静姐最多能向企业推荐的学生人数。
输入样例:
10 2 90 
203 0 
169 91 
175 88  
175 0 
175 90 
189 0 
189 0 
189 95 
189 89 
256 100 
输出样例:
8
样例解释:
第一批可以选择 175、189、203、256 这四个分数的学生各一名,此外 175 分 PAT 分数达到 90 分的学生和 189 分 PAT 分数达到 95 分的学生可以额外进入名单。第二批就只剩下 175、189 两个分数的学生各一名可以进入名单了。最终一共 8 人进入推荐名单。

思路:先把达到175分且PAT分数达到要求的人数先区分开来算,这些人属于k批次以外的人,然后对剩下那些过了175分,但是PAT分数没有达到要求的人去求它们的出现次数,因为一共只有k批次(同一批次的分数要求单调递增),所以,同一个分数顶多推荐k个人,超过就只算k个人,小于k就算出现的次数。

思路参考了http://t.csdn.cn/gXTkn

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
int n,k,s;
int d[1010];
int st[300];
struct nod
{
    int a,b;
}node[100010];
bool cmp(nod a,nod b)
{
    if(a.a!=b.a)
    return a.a=175&&node[i].b>=s)
        {
            sum++;
        node[i].a=-1;
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(node[i].a>=175)
            st[node[i].a]++;
    }
    for(int i=175;i<=290;i++)
    {
        if(st[i]>=k)
        {
            sum+=k;
        }else
        {
            sum+=st[i];
        }
    }
cout<

L2-1 插松枝 (25 分)

人造松枝加工场的工人需要将各种尺寸的塑料松针插到松枝干上,做成大大小小的松枝。他们的工作流程(并不)是这样的:
每人手边有一只小盒子,初始状态为空。
每人面前有用不完的松枝干和一个推送器,每次推送一片随机型号的松针片。
工人首先捡起一根空的松枝干,从小盒子里摸出最上面的一片松针 —— 如果小盒子是空的,就从推送器上取一片松针。将这片松针插到枝干的最下面。
工人在插后面的松针时,需要保证,每一步插到一根非空松枝干上的松针片,不能比前一步插上的松针片大。如果小盒子中最上面的松针满足要求,就取之插好;否则去推送器上取一片。如果推送器上拿到的仍然不满足要求,就把拿到的这片堆放到小盒子里,继续去推送器上取下一片。注意这里假设小盒子里的松针片是按放入的顺序堆叠起来的,工人每次只能取出最上面(即最后放入)的一片。
当下列三种情况之一发生时,工人会结束手里的松枝制作,开始做下一个:
(1)小盒子已经满了,但推送器上取到的松针仍然不满足要求。此时将手中的松枝放到成品篮里,推送器上取到的松针压回推送器,开始下一根松枝的制作。
(2)小盒子中最上面的松针不满足要求,但推送器上已经没有松针了。此时将手中的松枝放到成品篮里,开始下一根松枝的制作。
(3)手中的松枝干上已经插满了松针,将之放到成品篮里,开始下一根松枝的制作。
现在给定推送器上顺序传过来的 N 片松针的大小,以及小盒子和松枝的容量,请你编写程序自动列出每根成品松枝的信息。
输入格式:
输入在第一行中给出 3 个正整数:N(≤103),为推送器上松针片的数量;M(≤20)为小盒子能存放的松针片的最大数量;K(≤5)为一根松枝干上能插的松针片的最大数量。
随后一行给出 N 个不超过 100 的正整数,为推送器上顺序推出的松针片的大小。
输出格式:
每支松枝成品的信息占一行,顺序给出自底向上每片松针的大小。数字间以 1 个空格分隔,行首尾不得有多余空格。
输入样例:
8 3 4 
20 25 15 18 20 18 8 5 
输出样例:
20 15
20 18 18 8
25 5

赛后补题,比赛时卡了老半天结果只过了一个12的样例,属实亏死,数据结构的都没练过多少题,写起来还很生疏,这个代码还不知道是不是全对,之后能测试了再改过来

终于过了,这次认真看了题目,发现之前写的代码完全跟题目是反着来,简直离谱,这次按题目要求来模拟终于过了。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
int n,k,m;
vectorv[1010];
stacka;
int d[1010];
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)
        scanf("%d",&d[i]);
        int sum=1;

    for(int i=1;i<=n;i++)
    {

        //开一个新数组为空时的情况
        if(v[sum].size()==0&&!a.size())
        {
            v[sum].push_back(d[i]);
           if(v[sum].size()>=k)
            {
                    sum++;
                    continue;
            }
            continue;
        }else if(v[sum].size()==0&&a.size())
        {
            v[sum].push_back(a.top());
            a.pop();
             i--;
            if(v[sum].size()>=k)
            {
                    sum++;
                    continue;
            }
            continue;
        }
        //分界线
    if(a.size()&&a.top()<=v[sum][v[sum].size()-1])
        {
            v[sum].push_back(a.top());
            a.pop();
            i--;
            if(v[sum].size()>=k)
                {
                    sum++;
                    continue;
                }
        }else if(a.size()&&a.top()>v[sum][v[sum].size()-1])
        {

            if(d[i]<=v[sum][v[sum].size()-1])
            {
                v[sum].push_back(d[i]);
                if(v[sum].size()>=k)
                {
                    sum++;
                    continue;
                }
            }else
            {
                if(a.size()>=m)
                {
                i--;
                sum++;
                continue;
                }else
                {
                    a.push(d[i]);
                }
            }
        }
        else if(!a.size()&&d[i]<=v[sum][v[sum].size()-1])//栈为空时的情况1
        {
            v[sum].push_back(d[i]);
            if(v[sum].size()>=k)
                {
                    sum++;
                    continue;
                }
        }else if(!a.size()&&d[i]>v[sum][v[sum].size()-1])//栈为空时的情况2
        {
            a.push(d[i]);

        }

    }
    //如果栈里还有元素的话需要处理
while(a.size())
{
    if(v[sum].size()!=0)
    {
        if(v[sum][v[sum].size()-1]>=a.top())
        {
            v[sum].push_back(a.top());
            a.pop();
            if (v[sum].size()>=k)
            {
                sum++;
            }
        }else
        sum++;
    }
    if(v[sum].size()==0)
    {
    v[sum].push_back(a.top());
    if(v[sum].size()>=k)
        sum++;
    a.pop();
    }
}
//输出松枝信息
    for(int i=1;i<=sum;i++)
    {
        if(v[i].size()!=0)
        {

        for(int j=0;j

L2-2 老板的作息表 (25 分)

在这里插入图片描述

 新浪微博上有人发了某老板的作息时间表,表示其每天 4:30 就起床了。但立刻有眼尖的网友问:这时间表不完整啊,早上九点到下午一点干啥了?
本题就请你编写程序,检查任意一张时间表,找出其中没写出来的时间段。
输入格式:
输入第一行给出一个正整数 N,为作息表上列出的时间段的个数。随后 N 行,每行给出一个时间段,格式为:
hh:mm:ss - hh:mm:ss
其中 hh、mm、ss 分别是两位数表示的小时、分钟、秒。第一个时间是开始时间,第二个是结束时间。题目保证所有时间都在一天之内(即从 00:00:00 到 23:59:59);每个区间间隔至少 1 秒;并且任意两个给出的时间区间最多只在一个端点有重合,没有区间重叠的情况。
输出格式:
按照时间顺序列出时间表中没有出现的区间,每个区间占一行,格式与输入相同。题目保证至少存在一个区间需要输出。
输入样例:

13:00:00 - 18:00:00 
00:00:00 - 01:00:05 
08:00:00 - 09:00:00 
07:10:59 - 08:00:00 
01:00:05 - 04:30:00 
06:30:00 - 07:10:58 
05:30:00 - 06:30:00 
18:00:00 - 19:00:00 
输出样例:
04:30:00 - 05:30:00 
07:10:58 - 07:10:59 
09:00:00 - 13:00:00 
19:00:00 - 23:59:59 

靠,放着这么简单的一道题不做,去做前面那个麻烦的插松枝,我真的是服了我自己了。白白的25分就这样没了。

注:直接复制输入样例粘贴会出问题,只能输入个8先然后复制7行,最后一行再单独复制就可以正常输出答案。

改好了,这次这个全部能过了

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
int n,k,m;
int d[240010];
struct nod
{
    int l,r;

}node[240000];
bool cmp(nod a,nod b)
{
    return a.l

L2-3 龙龙送外卖 (25 分)

龙龙是“饱了呀”外卖软件的注册骑手,负责送帕特小区的外卖。帕特小区的构造非常特别,都是双向道路且没有构成环 —— 你可以简单地认为小区的路构成了一棵树,根结点是外卖站,树上的结点就是要送餐的地址。每到中午 12 点,帕特小区就进入了点餐高峰。一开始,只有一两个地方点外卖,龙龙简单就送好了;但随着大数据的分析,龙龙被派了更多的单子,也就送得越来越累……看着一大堆订单,龙龙想知道,从外卖站出发,访问所有点了外卖的地方至少一次(这样才能把外卖送到)所需的最短路程的距离到底是多少?每次新增一个点外卖的地址,他就想估算一遍整体工作量,这样他就可以搞明白新增一个地址给他带来了多少负担。

输入格式:

输入第一行是两个数 N 和 M (2≤N≤105, 1≤M≤105),分别对应树上节点的个数(包括外卖站),以及新增的送餐地址的个数。

接下来首先是一行 N 个数,第 i 个数表示第 i 个点的双亲节点的编号。节点编号从 1 到 N,外卖站的双亲编号定义为 −1。

接下来有 M 行,每行给出一个新增的送餐地点的编号 Xi​。保证送餐地点中不会有外卖站,但地点有可能会重复。

为了方便计算,我们可以假设龙龙一开始一个地址的外卖都不用送,两个相邻的地点之间的路径长度统一设为 1,且从外卖站出发可以访问到所有地点。

注意:所有送餐地址可以按任意顺序访问,且完成送餐后无需返回外卖站。

输出格式:

对于每个新增的地点,在一行内输出题目需要求的最短路程的距离。

输入样例:

7 4

-1 1 1 1 2 2 3

5

6

2

4

输出样例:

2

4

4

6

L2-4 大众情人 (25 分)


人与人之间总有一点距离感。我们假定两个人之间的亲密程度跟他们之间的距离感成反比,并且距离感是单向的。例如小蓝对小红患了单相思,从小蓝的眼中看去,他和小红之间的距离为 1,只差一层窗户纸;但在小红的眼里,她和小蓝之间的距离为 108000,差了十万八千里…… 另外,我们进一步假定,距离感在认识的人之间是可传递的。例如小绿觉得自己跟小蓝之间的距离为 2,则即使小绿并不直接认识小红,我们也默认小绿早晚会认识小红,并且因为跟小蓝很亲近的关系,小绿会觉得自己跟小红之间的距离为 1+2=3。当然这带来一个问题,如果小绿本来也认识小红,或者他通过其他人也能认识小红,但通过不同渠道推导出来的距离感不一样,该怎么算呢?我们在这里做个简单定义,就将小绿对小红的距离感定义为所有推导出来的距离感的最小值。
一个人的异性缘不是由最喜欢他/她的那个异性决定的,而是由对他/她最无感的那个异性决定的。我们记一个人 i 在一个异性 j 眼中的距离感为 Dij​;将 i 的“异性缘”定义为 1/maxj∈S(i)​{Dij​},其中 S(i) 是相对于 i 的所有异性的集合。那么“大众情人”就是异性缘最好(值最大)的那个人。
本题就请你从给定的一批人与人之间的距离感中分别找出两个性别中的“大众情人”。
输入格式:
输入在第一行中给出一个正整数 N(≤500),为总人数。于是我们默认所有人从 1 到 N 编号。
随后 N 行,第 i 行描述了编号为 i 的人与其他人的关系,格式为:
性别 K 朋友1:距离1 朋友2:距离2 …… 朋友K:距离K
其中 性别 是这个人的性别,F 表示女性,M 表示男性;K( 题目保证给出的关系中一定两种性别的人都有,不会出现重复给出的关系,并且每个人的朋友中都不包含自己。
输出格式:
第一行给出自身为女性的“大众情人”的编号,第二行给出自身为男性的“大众情人”的编号。如果存在并列,则按编号递增的顺序输出所有。数字间以一个空格分隔,行首尾不得有多余空格。
输入样例:
6
F 1 4:1
F 2 1:3 4:10
F 2 4:2 2:2
M 2 5:1 3:2
M 2 2:2 6:2
M 2 3:1 2:5
输出样例:
2 3
4
思路:先用佛洛依德求出每个人对别人的最小距离感,再求出这n个人,别人对他最大的距离感,存到一个数组里,再在这n个距离感里面求最小的距离感,男女要分开。

#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef pairPII;
const int N=510;
bool st[510];
int d[N][N];
int n;
vectorb,c;
void floyd()
{
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
        {
            d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
        }
}
bool cmp(PII a,PII b)
{
    if(a.first!=b.first)
    {
        return a.first>a;
       if(a!='F')
       {
           st[i]=true;
       }
       int m;
       scanf("%d",&m);
       while(m--)
       {
           int t,g;
           scanf("%d:%d",&t,&g);
           d[i][t]=min(d[i][t],g);
       }
   }
   floyd();
   for(int i=1;i<=n;i++)
   {
       int sum=0,num;
    for(int j=1;j<=n;j++)
   {
       if(i!=j&&st[j]!=st[i]&&d[j][i]>sum)
       {
           sum=d[j][i];
           num=i;
       }
   }
   if(st[i]==1)
   {
       b.push_back({sum,num});
   }else
   {
        c.push_back({sum,num});
   }
   }
   sort(b.begin(),b.end(),cmp);
    sort(c.begin(),c.end(),cmp);

for(int i=0;i<=c.size()-1;i++)
{
    if(c[i].first!=c[0].first)
        break;
    cout<

你可能感兴趣的:(天梯赛,其他)