HDU 6040 Hints of sd0061(nth_element)

【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=6040

【题目大意】

  给出一个随机数生成器,有m个询问,问第bi小的元素是啥
  询问中对于bi<bk,bj<bk,有bi+bj<=bk

【题解】

  我们将所有的询问排序,我们发现倒着处理询问的时候询问区间大小下降非常快,
  nth_element(start,start+k,end) 可以近似O(n)查询区间中第k小的数字,
  并且在处理后保证比第k小小的数字均在其前面(虽然不一定有序),
  所以我们直接倒着处理调用nth_element即可。

【代码】

#include <cstdio>
#include <algorithm>
using namespace std;
int T,n,m,id[110],b[110];
unsigned s[10000010],a[110],x,y,z;
unsigned xorshf96(){
    unsigned t;
    x^=x<<16;
    x^=x>>5;
    x^=x<<1;
    t=x; x=y; y=z;
    z=t^x^y;
    return z;
}
bool cmp(int x,int y){return b[x]<b[y];}
int main(){
    int Cas=1;
    while(~scanf("%d%d%u%u%u",&n,&m,&x,&y,&z)){
        for(int i=0;i<m;i++){id[i]=i;scanf("%d",&b[i]);}
        for(int i=0;i<n;i++)s[i]=xorshf96();
        sort(id,id+m,cmp);
        b[id[m]=m]=n;
        for(int i=m-1;~i;i--){
            if(b[id[i]]==b[id[i+1]]){
                a[id[i]]=a[id[i+1]];
                continue;
            }
            nth_element(s,s+b[id[i]],s+b[id[i+1]]);
            a[id[i]]=s[b[id[i]]];
        }printf("Case #%d: ",Cas++);
        for(int i=0;i<m-1;i++)printf("%u ",a[i]);
        printf("%u
",a[m-1]);
    }return 0;
}
原文地址:https://www.cnblogs.com/forever97/p/hdu6040.html