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\n",a[m-1]); }return 0; }
愿你出走半生,归来仍是少年