求第k大的数据
类似于快排。但是求第k个的递归子问题只有一个。
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <iostream>
template<typename T>
inline void swap(T& a, T& b)
{
T t = a;
a = b;
b = t;
}
// ================= 代码实现开始 ===================
// 在地址 [l,r) 范围内寻找 k 小值
template<typename T>
T find(T *l, T *r, int k)
{
int n = r - l;
if(n == 1)
return *l; //只有一个元素时就返回这个元素
bool a = 0;
swap( *(r-1), *(l+ rand() % n)); // rand()%n 产生一个从0到n-1的随机数
T val = *(r-1), *pos = l;
for(T *i = l; i < r-1; i++){
if(*i<val){
swap(*i,*pos);
pos++;
}else if(*i == val){
a^=1;
if(a){
swap(*i,*pos);
pos++;
//增加判断,如果与标准值相同,则一半放在左边一半放在右边,以保证复杂度
}
}
}
swap(*pos,*(r-1)); //再把元素换回来
int cur = pos - l + 1;
if(cur == k)
return *pos;
if(cur < k)
return find(pos+1,l+n, k-cur); //此时答案落在右半部分
//find(l+cur,l+n,k-cur);
return find(l,pos,k); //此时答案落在左半部分,递归的子问题只有一个复杂度O(n)
//find(l,l+cur,k);
}
// ============= 代码实现结束 ==============
#define maxn 30000000
int a[maxn + 10];
int main()
{
int n, k;
scanf("%d%d", &n, &k);
int p, q, M;
scanf("%d%d%d%d", a, &p, &q, &M);
for (int i = 1; i < n; i++)
a[i] = ((long long)p * a[i - 1] + q) % M;
printf("%d\n", find(a, a + n, k));
return 0;
}