队列之blah集合

时间:2021-02-06 18:55:46

  做了一个NOI上面的问题,叫blah集合,以a为基数,则2x+1和3x+1都在集合中,且集合中全部元素都由此计算得来。a∈[1,50],问升序排列后第n(n∈[1,1000000])个元素是多少。以输入示例a=1,n=100,b[n]=418为例:

集合中第一个元素(基数)为1,
      1  3  4  7 10 9 2x+
: 3     15 21 19…… 3x+: 4 10 13 22 31 27……

依次计算时会发现每1个数据会变为2个,这些数又会发生交叉。题目需要得到升序后第n个,我们如果先计算再排序一定会超时的,所以我们需要分别把2x+1和3x+1存储起来,然后取之前存储的较小的输出出来,队列很适合这项工作:

#include<iostream>
#include<queue>
typedef unsigned long long uint64;
using namespace std;
uint64 blah(int base,int maxid){
    int curval=base,curid=1;
    queue<uint64> x2,x3;
    x2.push(curval*2+1);
    x3.push(curval*3+1);
    while(maxid!=curid){
        if(x2.front()==x3.front()){
            curval=x2.front();
            x2.pop();
            x3.pop();
        }else if(x2.front()<x3.front()){
            curval=x2.front();
            x2.pop();
        }else{
            curval=x3.front();
            x3.pop();
        }
        x2.push(curval*2+1);
        x3.push(curval*3+1);
        curid++;
    }
    return curval;
}
int main(){
    int base,maxid;
    while(true){
        cin>>base>>maxid;
        cout<<blah(base,maxid)<<endl;
    }
}

不过遗憾的是,这份代码超时了,虽然它在我的计算机上计算得到结果是瞬间的事情。那么问题在哪呢?只能说可能出现在对front和pop的调用耗时上,当然也可能有内存分配方面的耗时。好吧,我们避免这些调用和重复的初始化——用数组来模拟一下队列:

#include<iostream>
typedef unsigned long long uint64;
using namespace std;
uint64 x2[1000000],x3[1000000];
uint64 blah(int base,int maxid){
    int curval=base,curid=1,x2id=0,x3id=0,x2cnt=0,x3cnt=0,x2val,x3val;
    x2[x2cnt]=curval*2+1;
    x3[x3cnt]=curval*3+1;
    while(maxid!=curid){
        x2val=x2[x2id];
        x3val=x3[x3id];
        if(x2val==x3val){
            curval=x2val;
            x2id++;
            x3id++;
        }else if(x2val<x3val){
            curval=x2val;
            x2id++;
        }else{
            curval=x3val;
            x3id++;
        }
        x2[++x2cnt]=curval*2+1;
        x3[++x3cnt]=curval*3+1;
        curid++;
    }
    return curval;
}
int main(){
    int base,maxid;
    while(scanf("%d %d",&base,&maxid)!=EOF){
        printf("%llu\n",blah(base,maxid));
    }
}

这份代码就以很短的时间通过了测试。