题目链接: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;
}