寒假训练记录一:排序问题

  感悟:刚开始学习排序,感觉这部分内容的基础知识较容易理解,没什么难懂的地方。不过随着这两天的刷题,还是学到了不少东西,发现有许多地方过去理解的还是过于浅显,希望自己在今后的学习中能对这些知识有更深刻的认识。

正文:

一、主要收获:(重点:结构体与sort、归并排序

1、qsort:快排即通过一个中间值,将待排数列划分为大于该值和小于该值的两部分,然后再递归调用qsort对两边分别排序。

其主要缺点就是不稳定:比如说现有一已知序列3、6、156、2、7,在一次划分后得到3、2、15667,最后排序得到的结果是1、2、3、5、667。然而这样就破坏了两个6的原有顺序,因此说它是不稳定的。

实现代码:

void qsort(int x,int y)
{
    int p=x,q=y,mid;   
    mid=a[(x+y)/2];    
    do
    {
        while(a[p]<mid)p++;     //此处p有判断作用,所以不可写为a[p++]<mid,下行同理。
        while(a[q]>mid)q--;
        if(p<=q)
            swap(a[p++],a[q--]);//无判断作用。
    }while(p<=q);
    if(p<y)qsort(p,y);
    if(q>x)qsort(x,q);
}

2、归并排序:

msort的实现可分为三个部分,①划分问题 ②递归对两半元素排序 ③合并两个有序

因此代码可写为:

void msort(int x,int y)
{
    if(x==y)return ;
    int mid=(x+y)/2;
    msort(x,mid);              //递归
    msort(mid+1,y);
    int p=x,q=mid+1,i=x;
    while(p<=mid||q<=y)             //合并操作
    {
        if(q>y||(p<=mid&&a[p]<=a[q]))r[i++]=a[p++];
        else r[i++]=a[q++];
    }
    for(i=x;i<=y;++i)a[i]=r[i];
}
同时,我们也可以借助合并函数merge()来实现归并排序:

merge(a,b,c,d,e,f)

四个参数分别表示:

a:左序列首地址    b:左序列末位置    c:右序列首位置    d:右序列末位置    e:存放结果的数组首地址

f:排序规则complare

例题:


题目描述

2*N 名编号为 1~2N 的选手共进行R 轮比赛。每轮比赛开始前,以及所有比赛结束后,都会按照总分从高到低对选手进行一次排名。选手的总分为第一轮开始前的初始分数加上已参加过的所有比赛的得分和。总分相同的,约定编号较小的选手排名靠前。

每轮比赛的对阵安排与该轮比赛开始前的排名有关:第1 名和第2 名、第 3 名和第 4名、……、第2K – 1 名和第 2K名、…… 、第2N – 1 名和第2N名,各进行一场比赛。每场比赛胜者得1 分,负者得 0 分。也就是说除了首轮以外,其它轮比赛的安排均不能事先确定,而是要取决于选手在之前比赛中的表现。

现给定每个选手的初始分数及其实力值,试计算在R 轮比赛过后,排名第 Q 的选手编号是多少。我们假设选手的实力值两两不同,且每场比赛中实力值较高的总能获胜。

输入输出格式

输入格式:

输入文件名为swiss.in 。

输入的第一行是三个正整数N、R 、Q,每两个数之间用一个空格隔开,表示有 2*N 名选手、R 轮比赛,以及我们关心的名次 Q。

第二行是2*N 个非负整数s1, s2, …, s2N,每两个数之间用一个空格隔开,其中 si 表示编号为i 的选手的初始分数。 第三行是2*N 个正整数w1 , w2 , …, w2N,每两个数之间用一个空格隔开,其中 wi 表示编号为i 的选手的实力值。

输出格式:

输出文件名为swiss.out。

输出只有一行,包含一个整数,即R 轮比赛结束后,排名第 Q 的选手的编号。

输入输出样例

输入样例#1:  复制
2 4 2 
7 6 6 7 
10 5 20 15 
输出样例#1:  复制
1

说明

【样例解释】

【数据范围】

对于30% 的数据,1 ≤ N ≤ 100;

对于50% 的数据,1 ≤ N ≤ 10,000 ;

对于100%的数据,1 ≤ N ≤ 100,000,1 ≤ R ≤ 50,1 ≤ Q ≤ 2N,0 ≤ s1, s2, …, s2N≤10^8,1 ≤w1, w2 , …, w2N≤ 10^8。

noip2011普及组第3题。

AC代码:

#include<bits/stdc++.h>
using namespace std;
struct node
{
   int strength,f_score,index;   //结构体在排序中常使用
}a[200001];
node b[100001],c[100001];

bool complare(node x,node y)
{
    if(x.f_score==y.f_score)return x.index<y.index;
    else return x.f_score>y.f_score;
}
int main()
{
    int N,R,Q;
    cin>>N>>R>>Q;
    for(int i=1;i<=2*N;++i)cin>>a[i].f_score,a[i].index=i;
    for(int i=1;i<=2*N;++i)cin>>a[i].strength;
    sort(a+1,a+1+N*2,complare);
    for(int i=1;i<=R;++i)
    {
        int p=1,q=1;
        for(int j=1;j<=2*N;j+=2)
        {
            if(a[j].strength>a[j+1].strength)
            {
                a[j].f_score+=1;
                b[p++]=a[j];
                c[q++]=a[j+1];
            }
            else
            {
                a[j+1].f_score+=1;
                c[q++]=a[j];
                b[p++]=a[j+1];
            }
        }
        merge(b+1,b+p,c+1,c+q,a+1,complare);

    }
    cout<<a[Q].index;
    return 0;
}
3、sort与结构体结合。

此部分目前感觉较简单,直接上例题,及AC代码:

题目描述

一共有n(n≤20000)个人(以1--n编号)向佳佳要照片,而佳佳只能把照片给其中的k个人。佳佳按照与他们的关系好坏的程度给每个人赋予了一个初始权值W[i]。然后将初始权值从大到小进行排序,每人就有了一个序号D[i](取值同样是1--n)。按照这个序号对10取模的值将这些人分为10类。也就是说定义每个人的类别序号C[i]的值为(D[i]-1) mod 10 +1,显然类别序号的取值为1--10。第i类的人将会额外得到E[i]的权值。你需要做的就是求出加上额外权值以后,最终的权值最大的k个人,并输出他们的编号。在排序中,如果两人的W[i]相同,编号小的优先。

输入输出格式

输入格式:

第一行输入用空格隔开的两个整数,分别是n和k。

第二行给出了10个正整数,分别是E[1]到E[10]。

第三行给出了n个正整数,第i个数表示编号为i的人的权值W[i]。

输出格式:

只需输出一行用空格隔开的k个整数,分别表示最终的W[i]从高到低的人的编号。

输入输出样例

输入样例#1:  复制
10 10
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
输出样例#1:  复制
10 9 8 7 6 5 4 3 2 1




AC:

#include<bits/stdc++.h>
using namespace std;
struct member
{
    int w;//初始权值
    int index;//初始编号
};
member a[20001];
int b[12];
bool complare1(member x,member y)
{
    if(x.w==y.w)return x.index<y.index;   //重点
    else return x.w>y.w;
}

int main()
{


    int n,k;
    cin>>n>>k;
    for(int i=1;i<=10;++i)cin>>b[i];
    for(int i=1;i<=n;++i)cin>>a[i].w,a[i].index=i;

    sort(a+1,a+1+n,complare1);
    for(int i=1;i<=n;++i)a[i].w+=b[(i-1)%10+1];
    sort(a+1,a+1+n,complare1);
    for(int i=1;i<=k;++i)cout<<a[i].index<<" ";
    return 0;
}
4、对于其他的选排,冒泡,桶排,插排等目前感觉较简单,也可能是做的题少,还没真正用上这些知识。


主要内容:本文详细介绍了一种QRBiLSTM(分位数回归双向长短期记忆网络)的时间序列区间预测方法。首先介绍了项目背景以及模型的优势,比如能够有效利用双向的信息,并对未来的趋势上限和下限做出估计。接着从数据生成出发讲述了具体的代码操作过程:数据预处理,搭建模型,进行训练,并最终可视化预测结果与计算分位数回归的边界线。提供的示例代码可以完全运行并且包含了数据生成环节,便于新手快速上手,深入学习。此外还指出了模型未来发展的方向,例如加入额外的输入特性和改善超参数配置等途径提高模型的表现。文中强调了时间序列的标准化和平稳检验,在样本划分阶段需要按时间序列顺序进行划分,并在训练阶段采取合适的手段预防过度拟合发生。 适合人群:对于希望学习和应用双向长短时记忆网络解决时序数据预测的初学者和具有一定基础的研究人员。尤其适用于有金融数据分析需求、需要做多一步或多步预测任务的从业者。 使用场景及目标:应用于金融市场波动预报、天气状况变化预测或是物流管理等多个领域内的决策支持。主要目的在于不仅能够提供精确的数值预计还能描绘出相应的区间概率图以增强结论置信程度。 补充说明:本教程通过一个由正弦信号加白噪构造而成的简单实例来指导大家理解和执行QRBiLSTM流程的所有关键步骤,这既方便于初学者跟踪学习,又有利于专业人士作为现有系统的补充参考工具。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值