hdu6040 Hints of sd0061(寻找第b[i]+1小的数)

来源:互联网 发布:找到网络打印机 编辑:程序博客网 时间:2024/05/29 19:00

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

题意:
用给定函数生成n个unsigned类型的数,用a数组保存,询问m次,每次询问a数组中第b[i]+1小的数是什么。

思路:
对a数组排序是不行的。题目中case<=10, n<1e7, m<=100, O(case * m *nlog(n))的复杂度是会超时的。

使用nth_element()函数。题目中有一点,b[i]+b[j] <= b[k], b[i]!=b[j], b[i] < b[k] , b[j] < b[k],我们把b[i],b[j],b[k]看成a数组中的下标ii, jj, kk, 那么kk可能比ii和jj大很多。那么,我们先把b数组排序,先查询a[kk], 再查询a[ii]和a[jj],这样我们可以把n的规模减小。

排序:
对b数组下标进行排序。另开一个数组idx,记录每个b[i]中的i,重定义小于号,将数组idx中下标i满足b[i]>b[j]的idx[i]排到前面。

代码:

#include <iostream>#include <algorithm>#include <cstring>#include <vector>#include <cstdio>using namespace std;const int maxn = 1e7+10;unsigned x, y, z;int n, m, A, B, C, Case, b[110], idx[110];unsigned a[maxn], ans[110];unsigned rng61() {  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 i, int j){    return b[i] > b[j];}int main(){    Case = 0;    while(cin>>n>>m>>A>>B>>C){        x=A; y=B; z=C;                for(int i=0; i<m; ++i){            cin>>b[i];            idx[i] = i;        }        for(int i=0; i<n; ++i){            a[i] = rng61();        }        sort(idx, idx+m, cmp);        int last = n;        for(int i=0; i<m; ++i){            int pos = b[idx[i]];            nth_element(a, a+pos, a+last);            ans[idx[i]] = a[pos];            last = pos;        }        cout<<"Case #"<<++Case<<":";        for(int i=0; i<m; ++i){            cout<<" "<<ans[i];        }        cout<<endl;    }    return 0;}
原创粉丝点击