【Luogu】 P1923 Encontre o k-ésimo menor número (dividir e conquistar + classificação rápida)

Descrição do título

Insira n (n <5000000 e n é um número ímpar) números ai (0 <ai <1 0 9) n (n <5000000 e n é um número ímpar) números a_i (0 <a_ (i) <10 ^ 9)n ( n<. 5 0 0 0 0 0 0 , en é um número ímpar ) um número de palavras aEu( 0<umaEu<1 09 ),produzaokkdesses númerosO número de k é pequeno. O menor número é0 00 pequeno.
Por favor, tente não usar nth_element para escrever esta questão, porque o foco desta questão é praticar o algoritmo de dividir para conquistar.

Entrada e saída de amostra

Entrada
5 1
4 3 2 1 5

Produto
2

Link do tópico: P1923 Encontre o menor número k

Ideias:

  • Você pode classificar a matriz diretamente e gerar o k-ésimo.
  • Divida e conquiste: use a ideia de classificação rápida, escolha o primeiro número (ou o último número) como a temperatura de referência, coloque o número menor ou igual à referência à esquerda e o número maior que a referência em à direita, então o número do benchmark é localizado. A posição é a mesma que sua posição na matriz classificada. A operação acima é chamada de divisão e cada divisão retornará um número de referência. Se a posição do número de referência após a divisão for k, significa que o número de referência atual é o k-ésimo número e é emitido diretamente. Se a posição do número de referência atual for maior que k, significa que o k-ésimo maior número está no intervalo correto do número de referência e só precisa ser dividido novamente no intervalo correto. Caso contrário, no intervalo à esquerda, basta dividir e pesquisar no intervalo à esquerda.

Divida e conquiste o código:

//AC代码:
#include<iostream>
#include<cstdio>
    using namespace std;
    const int N=5e6+100;
    int a[N];
    //做一次划分,归位基准数
    int p(int num[],int l,int r){
    
    
    int temp=num[l];
    while(l<r){
    
    
    while(l<r&&num[r]>temp) r--;
    num[l]=num[r];
    while(l<r&&num[l]<=temp) l++;
    num[r]=num[l];
    }
    num[l]=temp;
    return l;
    }
    //分治查找第k小的数
    int quicksort(int num[],int l,int r,int k){
    
    
    int x=p(num,l,r);
    if(x==k) return num[k];
    return x>k ? quicksort(num,l,x-1,k) :  quicksort(num,x+1,r,k);
    }
    int main(){
    
    
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    printf("%d\n",quicksort(a,0,n-1,k));
    return 0;
    }

Use nth_element:

  • Vendo esta função pela primeira vez, parece ser útil, familiarize-se com ela:

Arquivo de cabeçalho <algorithm>
void nth_element (RandomAccessIterator primeiro, RandomAccessIterator nth, RandomAccessIterator último);
void nth_element (first, nth, last);
Função: retornar o enésimo número no intervalo [primeiro, último).

//AC代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
    using namespace std;
    const int N=5e6+100;
    int a[N];
    int main(){
    
    
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    nth_element(a,a+k,a+n);   
    printf("%d\n",a[k]);
    return 0;
    }
  • Pode-se ver que nth_element (a, a + k, a + n) retorna o elemento no "endereço a + k" original na matriz, e "a + 0" é o 0º menor.

Acho que você gosta

Origin blog.csdn.net/IAMLSL/article/details/115251462
Recomendado
Clasificación