ACdream OJ 1099 瑶瑶的第K大 --分治+IO优化 - whatbeg

ACdream OJ 1099 瑶瑶的第K大 --分治+IO优化 - whatbeg

顺便把求数组中第K大数和求数组中第K小数的求法给出来。

代码:

/*
* this code is made by whatbeg
* Problem: 1099
* Verdict: Accepted
* Submission Date: 2014-06-15 00:13:53
* Time: 4340 MS
* Memory: 21212 KB
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <iomanip>
using namespace std;
#define N 1007

//复杂度O(n)
int Max_K(int a[],int low,int high,int k)
{
  if(k <= 0 || k > high-low+1)
    return -1;
  int flag = low + abs(rand())%(high-low+1);  //随机选择一个基准点
  swap(a[low],a[flag]);
  int mid = low;
  int cnt = 1;
  for(int i=low+1;i<=high;i++)
  {
    if(a[i] > a[low])   //遍历,把较大的数放在数组左边
    {
      swap(a[++mid],a[i]);
      cnt++;
    }
  }
  //比基准点大的数的个数为cnt-1
  swap(a[mid],a[low]);	//将基准点放在左、右两部分的分界处
  if(cnt > k)
    return Max_K(a,low,mid-1,k);
  else if(cnt < k)
    return Max_K(a,mid+1,high,k-cnt);
  else
    return mid;
}
 
int Min_K(int a[],int low,int high,int k)
{
  if(k <= 0 || k > high-low+1)
    return -1;
  int flag = low + abs(rand())%(high-low+1);
  swap(a[low],a[flag]);
  int mid = low;
  int cnt = 1;
  for(int i=low+1;i<=high;i++)
  {
    if(a[i] < a[low])
    {
      swap(a[++mid],a[i]);
      cnt++;
    }
  }
  swap(a[mid],a[low]);
  if(k < cnt)
    return Min_K(a,low,mid-1,k);
  else if(k > cnt)
    return Min_K(a,mid+1,high,k);
  else
    return mid;
}
 
inline int in()
{
  char ch;
  int a = 0;
  while((ch = getchar()) == ' ' || ch == '\n');
  a += ch - '0';
  while((ch = getchar()) != ' ' && ch != '\n')
  {
    a *= 10;
    a += ch - '0';
  }
  return a;
}
 
inline void out(int a)
{
  if(a >= 10)
    out(a / 10);
  putchar(a % 10 + '0');
}
 
int a[5000006];
 
int main()
{
  int n,k;
  while(scanf("%d%d",&n,&k)!=EOF)
  {
    getchar();
    for(int i=0;i<n;i++)
      a[i] = in();
    int res = Max_K(a,0,n-1,k);
    out(a[res]);
    puts("");
  }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值