排序2

洛谷P1583     

魔法照片  点击打开链接

1、双优先队列
#include<bits/stdc++.h>
using namespace std;
priority_queue<pair<int,int> > q;
priority_queue<pair<int,int> > q1;//自创算法:双优先队列。。。
int a[11];//保存额外权值
int main()
{
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=10;i++)
        cin>>a[i];//读入额外权值
    for(int i=1;i<=n;i++)
    {
        int h;
        cin>>h;
        q.push(make_pair(h,i*-1));//优先队列插入,i*-1是因为序号小的优先。
    }
    for(int i=0;i<n;i++)
    {
        int h=q.top().first;//记录原始值
        int v=q.top().second;//记录原始序号。
        q.pop();//弹
        h+=a[i%10+1];//根据题意,更新h值。
        q1.push(make_pair(h,v));//将h和v踢进第二个优先队列。
    }
    for(int i=0;i<k-1;i++)
    {
        cout<<q1.top().second*-1<<' ';//输出不细说。
        q1.pop();
    }
    cout<<q1.top().second*-1<<endl;
    return 0;
}
2、结构体+两次快速排序
#include<cstdio>
#include<algorithm>
using namespace std;
struct Person{
    int id,w;
}p[10000001]; //结构体,方便些
int n,k,E[11];
bool cmp(Person,Person); //排序的函数
int main(){
    scanf("%d%d",&n,&k); //输入
    for(int i=1;i<=10;i++) scanf("%d",&E[i]);
    for(int i=0;i<n;i++){
        scanf("%d",&p[i].w);
        p[i].id=i+1;    
    } 
    sort(p,p+n,cmp); //sort函数,需带algorithm头文件
    for(int i=0;i<n;i++)
        p[i].w+=E[i%10+1];
    sort(p,p+n,cmp); 
    for(int i=0;i<k;i++) printf("%d ",p[i].id); //输出
    return 0;    
}
bool cmp(Person a,Person b){
    if(a.w==b.w) return a.id<b.id;
    return a.w>b.w;
}
3、

题目实际上指的是先给定你1~n号对应的权值,从大到小排序后根据当前次序再编第二次号,分类别加上对应的e[i],再次从大到小进行排序后输出前k大权值分别的初始编号。

注意!第二次编号与最终的编号输出无关,仅用于分类。

举个例子:

输入:(测试点#1)

14 3 9 2 5 4 0 0 0 0 0 0

1 1 3 4 9 2 8 2 8 8 8 7 1 9

编号为:1 2 3 4 5 6 7 8 9 10 11 12 13 14

第一次排序后:(序号小优先)

9 9 8 8 8 8 7 4 3 2 2 1 1 1

编号为:5 14 7 9 10 11 12 4 3 6 8 1 2 13

类别为:1 2 3 4 5 6 7 8 9 10 1 2 3 4

加上e[i]后:18 11 13 12 8 8 7 4 3 2 11 3 6 5

第二次排序后:(序号小优先)

18 13 12 11 11 8 8 7 6 5 4 3 3 2

编号为:5 7 9 8 14 10 11 12 2 13 4 1 3

输出:5 7 9

这就是这道题大概的思路:输入——排号——排序——分类加e[i]——排序——输出

如果对上面的推导过程有什么疑问,可以自己动手尝试。

最后附上代码,希望能帮到大家(`・ω・´):

#include<cstdio>
#include<algorithm>
using namespace std;
int e[12],n,k;
struct person{
    int w;//权值 
    int num;//编号 
    int d;//类别 
}p[20010];//储存每个人的信息 
int w_comp(const person &a,const person &b){
    if(a.w!=b.w)return a.w>b.w;//从大到小排序 
    return a.num<b.num;//序号小优先 
}//结构体排序 
int main(){
    scanf("%d%d",&n,&k);
    for(int i=0;i<10;i++)scanf("%d",&e[i]);
    for(int i=0;i<n;i++){
        scanf("%d",&p[i].w);
        p[i].num=i+1;
    }//读入+编号 
    sort(p,p+n,w_comp);//第一次排序 
    for(int i=0;i<n;i++){
        p[i].d=i%10;//分类 
        p[i].w+=e[p[i].d];//加上e[i] 
    }
    sort(p,p+n,w_comp);//第二次排序 
    for(int i=0;i<k;i++)printf("%d ",p[i].num);
}
二、

 P1051 谁拿了最多奖学金

https://www.luogu.org/problemnew/show/P1051

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;
struct node{
    string xm;//姓名
    int qm,bj;//期末平均成绩,班级评议成绩
    char bgb,xb;//是否是学生干部,是否是西部省份学生
    int lw;//发表的论文数
    int ans;//个人所获的奖金数
    int sum;//序号数,因为题目要求两个人所获的奖金数相同时,输出先出现的,即序号较靠前的(较小的)
}a[101];
int n,tot=0;
bool cmp(node x,node y)
{
    if(x.ans==y.ans)return x.sum<y.sum;
    else return x.ans>y.ans;//奖学金数从大到小排序,相同时按序号数从小到大排序
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        cin>>a[i].xm>>a[i].qm>>a[i].bj>>a[i].bgb>>a[i].xb>>a[i].lw;
        if(a[i].qm>80&&a[i].lw>=1)a[i].ans+=8000;
        if(a[i].qm>85&&a[i].bj>80)a[i].ans+=4000;
        if(a[i].qm>90)a[i].ans+=2000;
        if(a[i].xb=='Y'&&a[i].qm>85)a[i].ans+=1000;
        if(a[i].bj>80&&a[i].bgb=='Y')a[i].ans+=850;
        a[i].sum=i;
        tot+=a[i].ans;//tot为总的奖学金数
    }
    sort(a+1,a+n+1,cmp);
    cout<<a[1].xm<<endl<<a[1].ans<<endl<<tot;
    return 0;
} 
结构体和快排

三、

 P1093 奖学金

https://www.luogu.org/problemnew/show/P1093

sort
#include<cstdio>
#include<algorithm>
using namespace std;
int n;
struct student{
    int c,m,e,tot,num;//定义 
}s[301];
int student_comp(const student &a,const student &b){//两个结构体 
    if(a.tot>b.tot)return 1;
    if(a.tot<b.tot)return 0;//总分比较 
    if(a.c>b.c)return 1;
    if(a.c<b.c)return 0;//语文比较 
    if(a.num<b.num)return 1;//序号比较 
    return 0;
}
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d%d%d",&s[i].c,&s[i].m,&s[i].e);//语数英读入 
        s[i].tot=s[i].c+s[i].m+s[i].e;//总分计算 
        s[i].num=i+1;//序号 
    }//读入 
    sort(s+0,s+n,student_comp);//排序 
    for(int i=0;i<5;i++)printf("%d %d\n",s[i].num,s[i].tot);//输出 
} 





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值