首页 > 编程语言 >[算法学习笔记] 浅谈二路归并&双指针&归并排序

[算法学习笔记] 浅谈二路归并&双指针&归并排序

时间:2023-09-21 22:46:27浏览次数:51  
标签:q1 q0 归并 浅谈 ++ 二路 int 数组

二路归并 · 双指针 是一种优化思想。它可以在 \(O(n)\) 的复杂度下把两个长度为 \(n\) 的有序数组合并为一个有序数组。

它的具体处理方法如下:

定义两个长度为 \(n\) 的升序数组 \(a,b\)。,合并完后长度为 \(2n\) 的数组 \(c\),初始化两个指针 \(x=y=1\)(这里数组下标从 \(1\) 开始)

  • 如果 \(a_x < b_y\),则 \(c_{cnt++}=a_x\),同时 \(x++\)。

  • 如果 \(a_x > b_y\),则 \(c_{cnt++}=b_y\),同时 \(y++\)

正确性显然,由于我们确保 \(a,b\) 数组升序,故如果 \(a_x < b_y\) ,则 \(b\) 数组从 \(y\) 以后的数一定大于 \(a_x\),所以按照顺序取 \(a_x\),同时移动 \(x++\)。

对于 \(a_x > b_y\) 同理。

由此可见,对于把一个长度为 \(n\) 的数组排序,我们可以分治,然后不断二路归并。这就是归并排序。

双指针思想应用广泛,接下来我们给出几个例题。

例题 · Luogu P1309 瑞士轮

经典永流传之瑞士轮。后面好多题目都用到了类似于瑞士轮的思想。

Link:https://www.luogu.com.cn/problem/P1309

我们发现每轮比赛都需要进行结构体排序,本题的复杂度显然无法接受。

注意到每轮比赛后胜利和失败是唯一的,不妨记录每轮比赛后胜利和失败的人,由于我们一开始确保数组有序,所以胜利和失败的人分数一定是单调递增的,可以二路归并。

实现
#include <iostream>
#include <cstdio>
#include <algorithm>
#define N 10010
using namespace std;
int n, m, k;
int s[N], w[N], q[N], q0[N], q1[N];
bool cmp(int a, int b)
{
    if (s[a] != s[b])
        return s[a] > s[b];
    return a < b;
}
int main()
{
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 0; i < n * 2; i++)
        scanf("%d", &s[i]);
    for (int i = 0; i < n * 2; i++)
        scanf("%d", &w[i]);
    for (int i = 0; i < n * 2; i++)
        q[i] = i;
    sort(q, q + n * 2, cmp);
    while (m--)
    {
        int t0 = 0, t1 = 0;
        for (int i = 0; i < n * 2; i += 2)
        {
            int a = q[i], b = q[i + 1];
            if (w[a] < w[b])
            {
                s[b]++;
                q0[t0++] = a;
                q1[t1++] = b;
            }
            else
            {
                s[a]++;
                q0[t0++] = b;
                q1[t1++] = a;
            }
        }
        int i = 0, j = 0, t = 0;
        while (i < t0 && j < t1)
            if (cmp(q0[i], q1[j]))
                q[t++] = q0[i++];
            else
                q[t++] = q1[j++];
        while (i < t0)
            q[t++] = q0[i++];
        while (j < t1)
            q[t++] = q1[j++];
    }

    printf("%d\n", q[k - 1] + 1);
}

标签:q1,q0,归并,浅谈,++,二路,int,数组
From: https://www.cnblogs.com/SXqwq/p/17721157.html

相关文章

  • 浅谈Node之express框架
    浅谈Node之express框架爱吃番茄的肥仔互联网数据开发一枚​关注他 4人赞同了该文章前言今天终于到了重点话题了,开始学习express框架,在学习之前我们需要了解express的作用和背景。express是一个web框架,功能和http模块类似,只不过功能更加强大,开发效......
  • [Spring]浅谈Spring的Resources体系
    Spring为什么要创建Resources体系Java的标准java.net.url类和各种URL前缀的标准处理程序无法满足所有对low-level资源的访问.举个例子:没有标准化的URL实现类用于获取根据ServletContext的类路径。并且缺少某些Spring所需要的功能,例如检测某资源是否存在等。ResourceSpring的Resour......
  • 智慧养殖:浅谈视频监控与AI智能识别技术助力奶牛高效、智慧养殖
    一、方案背景随着科技的飞速发展,智能化养殖逐渐成为现代畜牧业的发展趋势。人工智能技术、物联网、视频技术、云计算、大数据等新兴技术,正在为奶牛养殖业带来全新的变革。越来越多的牧场、养殖场开始运用新技术来进行智能监管、提高生产效率、降低生产成本,助力饲养成本高的养殖业,向......
  • 基础算法:快速排序、归并排序
    1、快速排序#include<iostream>usingnamespacestd;constintN=1e5+10;intn,q[N];voidqksort(intq[],intl,intr){if(l>=r)return;intx=q[l],i=l-1,j=r+1;while(i<j){doi++;while(q[i]<......
  • 浅谈这些年如何被MDK, IAR, GCC和厂家SDK版本兼容性“蹂躏”, 一代版本一代坑
     版本迭代是嵌入式开发永久的痛,这么多年不知道浪费了多少时间在版本迭代上。部分系统组件还好点,有个LTS长期支持版,而厂家SDK和IDE环境可谓惨不忍睹,一代版本一代坑。视频版:https://www.bilibili.com/video/BV1qu4y1d7wV【MDK】刚开始接触M内核芯片的时候就是用的这款IDE,最早有MDK2(......
  • 浅谈斜率优化
    众所周知,动态规划推出状态转移方程是很困难的,推出状态转移方程后发现复杂度爆炸是很炸裂的,所以这就是斜率优化存在的意义----降低转移方程的复杂度在看具体例子之前,我们先大致的介绍一下斜率优化的原理考虑一个这样的状态转移方程,f[i]=min{f[j]-k[i]*j+s[i]}  j<......
  • 深入了解归并排序算法
    归并排序(MergeSort)是一种高效的、基于分治法的排序算法,它的稳定性和性能使其成为常用的排序方法之一。本文将详细介绍归并排序的工作原理,提供示例和Python、Go、Java以及C语言的实现代码。归并排序的基本思想归并排序的核心思想是将数组分成两个子数组,递归地对这两个子数组进行排......
  • 构建工具gulp浅谈
    gulp.js-基于流(stream)的自动化构建工具引言:​ js作为一门脚本语言,在较早时候,只能通过<script>标签插进html去运行,单个的js文件离开了html就没有了意义。​ 如果一个网站功能很多,要按照功能划分写十几个js文件,那么就要插入十几个<scriptsrc="">去引那些js文件,还需要注意顺......
  • 归并排序
              ......
  • POJ 2299 Ultra-QuickSort ---归并排序 求逆序
    归并排序的模板。能求逆序。。。。#include<stdio.h>#include<string.h>intn;longlonga[500005],b[500005];longlongsum;voidmerge(intl,intm,intr){ inti=l,j=m+1,k=0; while(i<=m&&j<=r) { if(a[i]<=a[j]) b[k++]=a[i++]; else......