牛客黑龙江农垦科技职业学院喜迎寒假多校联赛

本文分享了作者在参加算法竞赛时遇到的题目及其解题思路,包括处理数组求和问题的优化方法、字符串排序的快速排序策略以及聊天记录分析的处理方式。通过实例解析了如何在有限的时间和空间限制内提高代码效率,强调了做题时的细心和全面思考的重要性。
摘要由CSDN通过智能技术生成

2021 .1.24
牛客黑龙江农垦科技职业学院喜迎寒假多校联赛
题解
从简单的来:
c链接:https://ac.nowcoder.com/acm/contest/11471/C
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
这一天gg拿到了一份,超多的考试数据a 。
老师要求他按照询问数据告诉老师,第几个到第几个同学的分数和是多少 ?
gg最近入职字节跳动了,没有时间处理这种极其简单的问题,所以请你顺手秒一下。

输入描述:
第一行n m ( n个同学 m次询问)
1<=n<=106
1<=m<=104
第二行输入n个整数表示成绩
a1 a2 …an (0<=ai<=100) 1<=i<=n
以下m行为两个整数bi bj 表示第几个到第几个同学(从1开始)
1<=bi<=bj<=n
输出描述:
m行查询结果
示例1
输入
复制
10 3
11 22 33 44 55 66 77 88 99 10
1 4
2 10
5 7
输出
复制
110
494
198
说明
注意第几个是按照输入顺序 不要排序 不要排序 不要排序

题意简单,就是输出按输入顺序从第 m 到第 n 之间总和
我的解法:如果一个一个循环会超时,所以做一个判断,判断输入的mn相差是否小于总数的一半
,如果小于那么直接做加法,如果大于则作减法 ,方法是来自南昌理工集训老师在讲交换时,用的交换数组两个例子从头和尾同时进行相加和减,从这想到了求总和,然后就是判断了。

代码如下:

#include<stdio.h>
#define M 1000000
int main()
{
    int a,b,x[M],i,m,n,s=0,j,k,l,num;
    scanf("%d%d",&a,&b);
        for(i=1;i<=a;i++)
            {
                scanf("%d",&x[i]);
                s=s+x[i];
            }
        for(j=0;j<b;j++)
        {   l=s;
            num=0;
            scanf("%d%d",&m,&n);
            if(n-m>=a/2)
            {
                for(i=1,k=a;i<m||k>n;i++,k--)
                {
                    if(i<m)
                        l=l-x[i];
                    if(k>n)
                        l=l-x[k];
                }
                printf("%d\n",l);
            }
            else if(n-m<a/2){
            for(i=m,k=n;i<=k;i++,k--)
            {   if(k!=i)
                num=num+x[i]+x[k];
                else
                    num=num+x[i];
            }
            printf("%d\n",num);
            }

        }
    return 0;
}

还有一种是来自讨论的代码意思是直接算出每个之前的和记录下来,再做减法,两个数相差的就是他们之间数的和
代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,m;
int h[1000006];
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        int x;
        scanf("%d",&x);
        h[i]=h[i-1]+x;
    }
    while(m--)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        printf("%d\n",h[y]-h[x-1]);
    }
    return 0;
}

题目感觉有点坑,第一次做没有心理准备,然后慢慢想,想如何才能减少时间,然后就过了。做题不可浮躁。

i&&h
链接:https://ac.nowcoder.com/acm/contest/11471/H
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld
题目描述
这一天cg写了一个卡迪亚酒店客户端,客户端的数据是一张由用户名s,密码m,性别x,电话h组成的表,他想以用户的用户名为基准进行一下排序,短的在前,同样长度按照字典序小的在前,同用户名先输入的在前面。但是曹哥太忙了所以找你帮忙写一下数据处理。
输入描述:
n分数据
1<=n<=100
以下n行 为 s m x h
1<= s.length <=20
1<= m.length <=20
1<= x.length <=20
1<= h.length <=20
输出描述:
根据用户名排序规则排序后输出
示例1
输入
复制
5
td1336065617 1336065617 n 13766949653
1336065617 1336065617 nc 137
ad1336065617 1336065617 na 111
03360651778 1 9 8
1 1 1 1
输出
复制
1 1 1 1
1336065617 1336065617 nc 137
03360651778 1 9 8
ad1336065617 1336065617 na 111
td1336065617 1336065617 n 13766949653
备注:
记得快读

题意:输入一个数n,然后输入n组数,按照从小到大的顺序和字符串比大小的顺序排列输出
i题就是加强版的h
题解:直接用sort快速排序的方法使用结构体进行排序,要按照题目的排序方法进行排序

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
struct x{
    int s;
    string a,b,c,d;
}hm[1000005];
bool cmp(x m,x n){
    if(m.a.length()!=n.a.length())
        return m.a.length()<n.a.length();
    if(m.a!=n.a)
        return m.a<n.a;
        return m.s<n.s;
}
int main(){
    int i,j,a;
    scanf("%d",&a);
    for(i=0;i<a;i++)
        {
            cin>>hm[i].a>>hm[i].b>>hm[i].c>>hm[i].d;
            hm[i].s=i;
        }
    sort(hm,hm+a,cmp);
    for(i=0;i<a;i++)
        cout<<hm[i].a<<" "<<hm[i].b<<" "<<hm[i].c<<" "<<hm[i].d<<endl;
        return 0;


}

题目不难,但是在赛中没有忘记将i值赋值给hm[i].s 所以总是百分之八十的对。
sort是冒泡的进阶版所以两题都可以过。

链接:https://ac.nowcoder.com/acm/contest/11471/J
来源:牛客网

题目描述
比赛开始了清楚姐姐喊了一句:签到了签到了 选手们纷纷开始签到,现在给出n个数字代表选手们签到所用秒数 请给出第几个选手最先签到。同秒数先输入的算快。
(不会吧 不会吧 不会有人用牛客不知道清楚姐姐吧)
输入描述:
第一行输入一个整数n
1<=n<=10000
第二行输入n个整数s
0<=s<=1000
输出描述:
一个数
示例1
输入
复制
5
5 3 2 4 1
输出
复制
5

题意:
输出最小秒数的位置。
签到题,之间敲出:

#include<iostream>
#include<algorithm>
#include<cstdio>
int main()
{

    int a,x[1000]={0},i,n,m;
    scanf("%d",&a);
    for( i=0;i<a;i++)
        scanf("%d",&x[i]);
        n=x[0];m=0;
    for(i=1;i<a;i++)
   if(n>x[i])
   {
       n=x[i];
      m=i;
   }

    printf("%d",m+1);
        return 0;
}

链接:https://ac.nowcoder.com/acm/contest/11471/G
来源:牛客网

题目描述
又是欢快的一天,牛客多校算法训练营4又在日常%Alan。qcjj想知道到底Alan被%了多少次,所以整理了一下聊天记录。
如果一句话中存在Alan,那么那句话中的%都算%了Alan。由于可能话中有空格,所以去掉空格后形成的Alan也算Alan。
输入描述:
第一行输入整数n表示聊天记录行数
1<=n<=1000
以下n行每行一个字符串s代表聊天记录
1<=s.length<=1000
输出描述:
输出%Alan次数
示例1
输入
复制
5
%alan%%
%Alan%%%
cdqwsq%% A l a n%%
%AC lan%%
%Alan%%%
输出
复制
12

题意:
输入一个数 n ,然后就是输入n组字符串,进行读如果有Alan则输出这行的%个数,然后将总的%个数输出。
题解:
自己本身不会太高端的方法,只能一个一个读但是要注意Alan之间不可以有其他一切的东西,除了空格,
所以读时记录每个字符的个数,如果读了超过之前字符的个数(除了最后一个字符n),那么就所有变量清零,如果是A超过那么记录A的变量为一其他归0.还有就是如果一行只要有了一组可以拼在一起的Alan就可以了。要注意单词之间不可以有其他字符,如果有也是全部清零。暴力方法,只要注意细节就可以了。

代码如下:

#include<stdio.h>
#include<string.h>
int main(){
    int y,a,i,m=0,n,a1,l,s,z=1,d=0;
    char x[1005];
    scanf("%d",&y);getchar();
    a=0;
    a1=0;l=0;n=0;s=0;
    for(int j=0;j<y;j++)
      {   m=0;a=0;a1=0;l=0;n=0;
            gets(x);d=0;
          for(i=0;i<strlen(x);i++)
          {
            if(a>=1&&a1>=1&&l>=1&&n>=1)
                d=1;
              if(x[i]=='%')
                    m++;
                if(x[i]=='A')
                    {a1++;if(a1>=2){a1=1;l=0;a=0;n=0;}}
                if(a1>=1 && x[i]=='l')
                    {l++;if(l>=2){a1=0;l=0;a=0;n=0;}}
                if(a1>=1 && l>=1 && x[i]=='a')
                    {a++;if(a>=2){a1=0;l=0;a=0;n=0;}}
                if(a1>=1 && a>=1 && l>=1 && x[i]=='n')
                    {n++;if(n>=2){a1=0;l=0;a=0;n=0;}}
                    if(a1>=1||a>=1||l>=1||n>=1)
                    {
                        if(x[i]=='a'||x[i]=='A'||x[i]=='l'||x[i]=='n'||x[i]==' '||x[i]=='%')
                                z=0;
                        else {
                                a1=0;l=0;a=0;n=0;
                        }
                    }

                if(x[i]=='\0')break;

          }
          if((a>=1&&a1>=1&&l>=1&&n>=1)||d==1)
            s=s+m;
      }
      printf("%d",s);
      return 0;
    }

这题不难但是对于我这种小菜鸟来说在赛时,要小心,要细心,要考虑周全,。不然就会因小失大。

剩下的题目还没有完全搞定。。。。。
敬请期待。。。。。。。。。。。。。

链接:https://ac.nowcoder.com/acm/contest/11471/E
来源:牛客网

题目描述
这一天Kadia与Majiagou在教学弟,
突然提出了一个问题 给你一个超大的数字 让你从中删掉几位 怎么让他最小?
这种签到题不会还有人写不出来吧 不会吧不会吧
输入描述:
第一行输入一个整数N
1<=len(N)<=2×107
第二行输入一个整数k代表删除几个数字
0<=k<=len(N)
输出描述:
输出结果
示例1
输入
复制
10000
1
输出
复制
0
说明
删掉1结果为0
示例2
输入
复制
12347897187194164979
10
输出
复制
1114164979

有没有ak大佬教一下第e题呀
这是我找到最简单的代码,但是还是看不懂什么意思,有没有大佬评论一下这代码的思路是什么呀,,,‘
根本看不懂思路,哪怕每一步都输出相应变量都看不懂。。。。

#include <stdio.h>
#include <string.h>
const int N = 2e7 + 5;
char s[N];
int main()
{
    int k, i, j;
    scanf("%s%d", s,&k);
    for(i = 0,j = 1;s[j - 1] > 0;)
        if(k <= 0 || s[i] <= s[j]) s[++i] = s[j++];
        else
        {
            i--; k--;
        }
    int len = strlen(s);
    for(i = 0; s[i] == '0' && i < len - 1; i++);
    printf("%s", s + i);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值