2020大一寒假培训二 (排序和cmp函数)

ACM集训二

E 没必要的排序2
没必要的排序2
Problem:E
Time Limit:3000ms
Memory Limit:65535K
Description
羽裳有n个数,她想知道前k大的数的和是多少
Input
输入n,k代表有n个数,求前k大的和,之后输入n个数,第i个数为a[i]
1<=n<=10000000(1e7)
1<=k<1000
对任意的i
1<=a[i]<=100000(1e5)
Output
输出一个数ans,ans是前k大数的和
Sample Input
2 1
99999 1
Sample Output
99999
Hint
排序会超时

#include <bits/stdc++.h>

using namespace std;
const int N=1e7+10;//(定义输入数字的范围)
int a[N];
int main()
{
    int n,k,i,x,j,flag,ans;
    while(cin>>n>>k)
    {
        flag=0;ans=0;
        for(i=0;i<n;i++)
        {
            cin>>x;
            a[x]++;
        }
        for(j=N;j>=0;j--)//(所有可能输入的情况计算)
        {
          if(a[j]!=0)
          {
              flag=flag+a[j];
               ans=ans+a[j]*j;

          }

          if(flag>=k)
          {
              ans=ans-(flag-k)*j;
              break;//(不跳出会多减
          }

        }

  cout<<ans<<endl;
    }

    return 0;
}

F 老和尚的导员
没必要的排序2
Problem:E
Time Limit:3000ms
Memory Limit:65535K
Description
羽裳有n个数,她想知道前k大的数的和是多少
Input
输入n,k代表有n个数,求前k大的和,之后输入n个数,第i个数为a[i]
1<=n<=10000000(1e7)
1<=k<1000
对任意的i
1<=a[i]<=100000(1e5)
Output
输出一个数ans,ans是前k大数的和
Sample Input
2 1
99999 1
Sample Output
99999
Hint
排序会超时

#include <bits/stdc++.h>

using namespace std;
struct student
{
    int a[5],x,y,z;
};
bool cmp(student m,student n)//我是这样理解cmp的,两个比较第一个比第二个大就是从大到小排序
{
    if(m.z!=n.z) return m.z>n.z;
    else if(m.a[1]!=n.a[1])return m.a[1]>n.a[1];
    else if(m.a[2]!=n.a[2])return m.a[2]>n.a[2];
    else if(m.a[3]!=n.a[3])return m.a[3]>n.a[3];
    else if(m.a[4]!=n.a[4])return m.a[4]>n.a[4];

}
int main()
{
    int i,n;
    student stu[100];
    while(cin>>n)
    {
        for(i=1;i<=n;i++)
        {
            cin>>stu[i].a[1]>>stu[i].a[2]>>stu[i].a[3]>>stu[i].a[4];
            stu[i].z=stu[i].a[1]+stu[i].a[2]+stu[i].a[3]+stu[i].a[4];
            stu[i].x=i;
        }

        sort(stu+1,stu+n+1,cmp);//用cmp规定的来排
        for(int i=1;i<=n;i++)
        {
            cout<<stu[i].x<<" "<<stu[i].z<<endl;//打上空格
        }
    }
    return 0;
}

G 健忘的老和尚
健忘的老和尚
Problem:G
Time Limit:1000ms
Memory Limit:65536K
Description
当小和尚排完名单后,老和尚突然一拍脑袋:“导员把每个人的人名都给我了,可我忘记告诉你了。”好吧……我们可怜的小和尚看来要费二遍事了(好像之前的任务都是你帮他做的,好吧,你真可怜)
Input
输入数据为多组,输入的第一行为和尚的人数N,可以得到奖学金的人数M,和需要补考的人数O(在这里可以满足M+O<=N,即得到奖学金的和尚一定不用参加补考)。之后的N行每行都有一个字符串(即为和尚的名字,长度小于100)和尚考试的总分a[i](0 <= a[i] <= 1000)。
Output
前M行,每行是获得奖学金的小和尚的名字;
后O行,每行是补考的小和尚的名字;
由于老和尚觉得很对不起小和尚,所以他决定这次简单些,所以无论是奖励还是惩罚都按照总成绩从低到高输出和尚的名字即可。
Sample Input
5 1 2
a 192
aa 212
ab 351
bab 128
bbaa 654
Sample Output
bbaa
bab
a

#include <bits/stdc++.h>

using namespace std;
struct student
{
    int sum;
    char name[101];//题目没写明白,人数最大是100,不能定小了
};
bool cmp(student a,student b)
{
    return a.sum<b.sum;
}
int main()
{
    int i,n,m,o;
    student stu[200];
    while(cin>>n>>m>>o)
    {
        for(i=1;i<=n;i++)
        {
            cin>>stu[i].name>>stu[i].sum;
        }

            sort(stu+1,stu+n+1,cmp);

      for(int i=n-m+1;i<=n;i++)
      {
          cout<<stu[i].name<<endl;
      }
      for(int i=1;i<=o;i++)
      {
          cout<<stu[i].name<<endl;
      }
    }
    return 0;
}

H 戏说三国
戏说三国
Problem:H
Time Limit:1000ms
Memory Limit:65536K
Description
东汉末年,宦官当权,民不聊生。灵帝中平元年,张角兄弟发动黄巾起义,官军闻风丧胆。为抵抗黄巾,幽州太守刘焉出榜招兵。榜文前,刘备、关羽、张飞三兄弟萍水相逢。三人都有为国效力之心,于是桃园结为异姓兄弟,开始了一段三国浪漫传奇……
如果我问你三国中谁最聪明你一定会说是诸葛亮,我要问你谁武功最高,保不准你就要说关羽。是啊,我们的刘备对于优秀的手下向来十分满意。可是有一天,刘备在无意间在朋友圈里看到了梁山的宋江正在进行英雄排座次,最可气的是这条动态已经被转发评论了无数次了……这一下可气坏了刘备,他决定也来一次,蜀中文武百官大排名。
为了公平起见,诸葛亮帮他制定一条评分标准:每个官员有一个智育、德育、武育三个分数,分别以b%,a%,c%的比率计入加权总分,按总分降序排列,总分相同按智育折合后的分数降序,智育相同按德育,依次类推最终决定排名。(保证没有排名一样的两个人)
Input
输入第一行t(1<=t<=1000)表示输入的组数。接下来每组第一行1个整数n(1<=n<=100000)三个实数a,b,c(a+b+c=100)接下来n行每行包括英雄的名字,字符串s(1<=len<=20,全为小写字母) 智育、德育、武育的分数(整数)。(1~100)
Output
每组第一行输出是第几组输出Case #t:接下来输出n行每行包括英雄的名字,总分,智育、德育、武育折合后的分数(保留四位小数)。
Sample Input
1
3 20.00 20.00 60.00
zhugeliang 90 80 0
zhangfei 0 0 100
guanyu 10 100 100
Sample Output
Case #1:
guanyu 82.0000 2.0000 20.0000 60.0000
zhangfei 60.0000 0.0000 0.0000 60.0000
zhugeliang 34.0000 18.0000 16.0000 0.0000

#include <bits/stdc++.h>

using namespace std;
struct wj
{
    char name[100];
    double z,d,w,zf;
    int x;
};
bool cmp(wj a,wj b)
{
    if(a.zf!=b.zf) return a.zf>b.zf;
    else if(a.z!=b.z) return a.z>b.z;
    else if(a.d!=b.d) return a.d>b.d;
    else if(a.w!=b.w) return a.w>b.w;
}
int main()
{
    int t,i,n;
    double a,b,c;
    wj stu[100000];
    cin>>t;
    for(int r=1;r<=t;r++)
    {
         cin>>n>>b>>a>>c;
        for(int i=1;i<=n;i++)
        {
            cin>>stu[i].name>>stu[i].z>>stu[i].d>>stu[i].w;
            stu[i].zf=stu[i].z*(a/100)+stu[i].d*(b/100)+stu[i].w*(c/100);
        }

    sort(stu+1,stu+n+1,cmp);
    printf("Case #%d:\n",r);
    for(int i=1;i<=n;i++)
    {
           printf("%s %.4f %.4f %.4f %.4f\n",stu[i].name,stu[i].zf,stu[i].z*(a/100),stu[i].d*(b/100),stu[i].w*(c/100));
    }
    }
    return 0;
}

I 相约摩洛哥
相约摩洛哥
一样是排序,只是条件多

Problem:I
Time Limit:1000ms
Memory Limit:65536K
Description
2015年5月ACM全球总决赛在摩洛哥卡萨布兰卡举行,到时会有来自世界各地的acm大牛齐聚摩洛哥。

作为本次大赛的举办方负责人阿焜和阿祥被分配给了一个重要的任务,就是在比赛中统计大家的排名。
acm大赛排名规则(摘自百度百科):
最后的获胜者为正确解答题目最多且总用时最少的队伍。每道试题用时将从竞赛开始到试题解答被判定为正确为止,其间每一次提交运行结果被判错误的话将被加罚20分钟时间,未正确解答的试题不记时。例如:A、B两队都正确完成两道题目,其中A队提交这两题的时间分别是比赛开始后1:00和2:45,B队为1:20和2:00,但B队有一题提交了2次。这样A队的总用时为1:00+2:45=3:45而B队为1:20+2:00+0:20=3:40,所以B队以总用时少而获胜。
请你帮他俩完成这项任务吧!(保证没有成绩完全相同两支队伍)
Input
多组输入,每组一个正整数n(1<=n<=100000),代表有n个队伍参赛。接下来的n行,每行分别有一个字符串(只包含小写英文字母)作为队伍名,长度1<=len<=10;ABC三道题的ac时间(以分钟为单位),时间为-1表示该题没有ac。接下来又有n行,表示每道题的提交次数,用3个正整数表示。
Output
输出排行榜。n行,每行一个队伍的名字、解题数和总用时。
Sample Input
3
team 30 10 20
behappy 20 20 90
newbee 15 16 17
1 1 1
1 1 10
1 1 1
Sample Output
newbee 3 48
team 3 60
behappy 3 310

#include <bits/stdc++.h>

using namespace std;
struct student
{
    char name[100];
    int a[5],b[5],sj,jts;//可以用数组代替具体字母
};
bool cmp(student a,student b)
{
   if(a.jts!=b.jts) return a.jts>b.jts;
   else if(a.jts==b.jts) return a.sj<b.sj;
}
int main()
{
    int n;
    student stu[1000];
    while(cin>>n)
    {
        for(int i=1;i<=n;i++)
        {
            cin>>stu[i].name>>stu[i].a[1]>>stu[i].a[2]>>stu[i].a[3];
        }
        for(int i=1;i<=n;i++)
        {
            cin>>stu[i].b[1]>>stu[i].b[2]>>stu[i].b[3];
        }
        for(int i=1;i<=n;i++)
        {
            stu[i].sj=stu[i].jts=0;
            for(int j=1;j<=3;j++)
            {
                if(stu[i].a[j]!=-1)
                {
                   stu[i].jts++;
                   stu[i].sj=stu[i].sj+stu[i].a[j]+20*(stu[i].b[j]-1);
                }
            }
        }
        sort(stu+1,stu+n+1,cmp);
        for(int i=1;i<=n;i++)
        {
            cout<<stu[i].name<<" "<<stu[i].jts<<" "<<stu[i].sj<<endl;
        }

    }
    return 0;
}

I 结构体排序题一
结构体排序题一
Problem:J
Time Limit:1000ms
Memory Limit:65535K
Description
现在给定一组二维平面上面的点的坐标,保证它的坐标是int类型的整数且大于等于0小于等于99.请你按照数据所给要求进行排序.
首先先以横坐标进行排序,若横坐标相同则按纵坐标排序,降序或升序将以0和1的形式表示,0表示降序,1表示升序.
比如,若数据开头给出0 1的要求,则表示先以横坐标降序排列,若横坐标相同则按纵坐标升序排列.
再比如,若数据开头给出1 1的要求,则表示先以横坐标升序排列,若横坐标相同则按纵坐标升序排列.
保证点的数量大于等于3小于等于99
Input
第1行包含三个数字,第一个数字和第二个数字分别表示横坐标和纵坐标的排序要求,0表示降序,1表示升序,第三个数字n表示有几个点需要排序.
余下第2~n+1行每行各有两个类型为n个点的坐标,例如第2行第一个数字表示第一个点横坐标,第二个数字表示第一个点的纵坐标.
Output
输出n行坐标,一行表示一个点,格式如下:
(x0,y0)
Sample Input
0 0 4
1 1
1 2
2 1
2 2
1 1 4
2 2
2 1
1 2
1 1
Sample Output
(2,2)
(2,1)
(1,2)
(1,1)
(1,1)
(1,2)
(2,1)
(2,2)

#include <bits/stdc++.h>

using namespace std;
struct zb
{
    int a,b;
};
int x,y;
bool cmp(zb j,zb k)
{
   if(j.a!=k.a){
    if(x==1) return j.a<k.a;
    else return j.a>k.a;
   }
    if(y==1) return j.b<k.b;
    else return j.b>k.b;
}
int main()
{
    int n,x,y;
    zb stu[1000];
    while(cin>>x>>y>>n)
    {
       for(int i=1;i<=n;i++)
       {
           cin>>stu[i].a>>stu[i].b;
       }
       sort (stu+1,stu+n+1,cmp);
       for(int i=1;i<=n;i++)
       {
           printf("(%d,%d)\n",stu[i].a,stu[i].b);
       }
    }
    return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值