集合的第N大元素

来源:互联网 发布:淘宝遇到诈骗怎么办 编辑:程序博客网 时间:2024/05/01 18:07

Description

有一个集合满足下面的关系:
    1)1属于该集合;
    2)如果x属于该集合,则2x+1和3x+1也属于该集合;
    3)集合中再无其它的元素。
请你求出集合的前n小的元素。

Input

一个整数N(N<=200000)

Output

一行,N个不同的整数,由小到大排列,用空格间隔

Sample Input

5

Sample Output

1 3 4 7 9

【分析】

        如果按照每一个生成数据的顺序去扩展它的两个“子数据”,那么这样得到的序列是无序的,也就无法找到集合的第n大的元素。 一个简单的想法是能否先生成充足的数字,然后排序找出其中的第n大的元素。虽然时间能勉强承受,但有一个问题,我们不知道该生成多少元素才能生成n以内所有的元素。

        于是,便用单调队列。方法很简单,就是再拿两个队列来分别扩展2*x+1和3*x+1,每次取出较小的队首元素,作为输入,然后再用这个值给两个队列队尾添加元素。
 
【代码】
#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<ctime>#include<iostream>#include<algorithm>using namespace std;const int INF=0x7FFFFFFF;int N,x,a[200005],b[200005];void _init(){scanf("%d",&N);for(int i=1;i<=N;i++){a[i]=INF;b[i]=INF;}}void _solve(){int atail=1,ahead=1,btail=1,bhead=1;x=1;for(int i=1;i<=N;i++){printf("%d ",x);b[btail++]=x*2+1;a[atail++]=x*3+1;if(b[bhead]<a[ahead])    x=b[bhead++];else    x=a[ahead++];if(b[bhead]==x)    bhead++;}printf("\n");}int main(){_init();_solve();return 0;}