• HDU 6040 Hints of sd0061(划分高低位查找)


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

    【题目大意】

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

    【题解】

      (By Claris)对于所有的数字,我们将其按照高位分类,统计每个高16位有几个数字,
      然后定位每个询问的高16位是什么,因为只有100个高16位是被询问到的,
      把这100个高16位的数放入桶里,每次暴力查找,因为数据随机,
      因此每个高16位期望n/65536=153个数,一共只有15300个数字有用

    【代码】

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    int T,n,m,k[200],pos[200];
    unsigned s[10000010],b[10000010],x,y,z;
    unsigned q[65536],cnt[65536],u[65536],tot[65536];
    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;
    }
    int getpos(int x){for(int i=0;;i++)if(tot[i]>=x)return i;}
    unsigned query(int k,int p){
        int i=p?tot[p-1]:0,m=0;
        for(k-=++i;i<=tot[p];i++)q[m++]=b[i];
        nth_element(q,q+k,q+m); 
        return q[k];
    }
    int Cas=1;
    int main(){
        while(~scanf("%d%d%u%u%u",&n,&m,&x,&y,&z)){
            for(int i=0;i<65536;i++)cnt[i]=u[i]=0;
            for(int i=1;i<=n;i++){s[i]=xorshf96();cnt[s[i]>>16]++;}
            for(int i=1;i<65536;i++)cnt[i]+=cnt[i-1];
    		for(int i=0;i<65535;i++)tot[i]=cnt[i];
            for(int i=1;i<=m;i++){
                scanf("%d",&k[i]);
                pos[i]=getpos(++k[i]);
                u[pos[i]]=1;
            }for(int i=1;i<=n;i++)if(u[s[i]>>16])b[cnt[s[i]>>16]--]=s[i];
            printf("Case #%d:",Cas++);
            for(int i=1;i<=m;i++)printf(" %u",query(k[i],pos[i]));
            puts("");
        }return 0;
    }
  • 相关阅读:
    倍增_ST表与LCA
    树状数组
    CF1365B 题解
    左偏树
    ES5_04_Array扩展
    ES5_03_Object扩展
    ES5_05_Function扩展
    前台样式与实际开发应用
    利用Mircosoft URLRewriter.dll实现页面伪静态(伪静态系列一)
    递归算法常见习题代码(控制台程序)
  • 原文地址:https://www.cnblogs.com/forever97/p/hdu6040plus.html
Copyright © 2020-2023  润新知