题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6040
题意:不知道北航的同学为何解释题意之前都要想一段故事,导致刚开始题意不是很懂,题意就是给你n,m,A,B,C三个点,可以用以下这段代码生成n个随机数,赋值num[N],然后给你m个数,作为m次询问赋值给q[N]。然后问你第i次询问对于区间(0,n)这个区间中第q[i]+1小的数。
unsigned x = A, y = B, z = C; 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; }
思路:好吧……我是看了别人的代码,学习了这个线性求k大的姿势,就是用了一个STL的库函数nth_element(start,start+n,end);这个函数找的是[start,end)这个左闭右开区间内部第n+1大的数,感觉这个题就是为这个函数设计的。因为他是把拍完序以后应该在下标为n的位置的数归位,n左边的数比他小,右边的数比他大(不完全快排),这个题还有一个优化的地方,就是减少排序区间。我们先处理大的询问再处理小的询问。我举个例子,比如54321,现在我要求第5小的数,是5,处理完以后数组可能是43215,5是归位的但是其他数还是乱序的。然后我再在[0,4)这个区间内部去找第4小的数,和我原来要在[0,5)这个区间内部去找第四小的数结果是一样的。这样做的优点在于我们逐渐减少了,处理的区间加快了速度。这个题是个暴力题,如果没有这个优化是会超时的。
代码:

1 //Author: xiaowuga 2 #include <iostream> 3 #include <algorithm> 4 #include <set> 5 #include <vector> 6 #include <queue> 7 #include <cmath> 8 #include <cstring> 9 #include <cstdio> 10 #include <ctime> 11 #include <map> 12 #include <bitset> 13 #include <cctype> 14 #define maxx INT_MAX 15 #define minn INT_MIN 16 #define inf 0x3f3f3f3f 17 #define mem(s,ch) memset(s,ch,sizeof(s)) 18 #define da cout<<da<<endl 19 #define uoutput(a,i,l,r) for(int i=l;i<r;i++) if(i==l) cout<<a[i];else cout<<" "<<a[i];cout<<endl; 20 #define doutput(a,i,l,r) for(int i=r-1;i>=0;i--) if(i==r-1) cout<<a[i];else cout<<" "<<a[i];cout<<endl; 21 const long long N=1e7+10; 22 using namespace std; 23 typedef long long LL; 24 unsigned x,y,z; 25 unsigned rng61() { 26 unsigned t; 27 x ^= x << 16; 28 x ^= x >> 5; 29 x ^= x << 1; 30 t = x; 31 x = y; 32 y = z; 33 z = t ^ x ^ y; 34 return z; 35 } 36 unsigned num[N]; 37 unsigned ans[N],ca=0; 38 pair<int,int>q[100+10]; 39 int cmp(pair<int,int>a,pair<int,int>b){ 40 return a.first<b.first; 41 } 42 int main() { 43 ios::sync_with_stdio(false);cin.tie(0); 44 unsigned n,m; 45 while(cin>>n>>m>>x>>y>>z){ 46 for(int i=0;i<n;i++) num[i]=rng61(); 47 for(int i=0;i<m;i++) {cin>>q[i].first;q[i].second=i;} 48 sort(q,q+m,cmp);//从小到大排序 49 q[m].first=n; 50 q[m].second=m; 51 for(int i=m-1;i>=0;i--){ 52 //我们知道q[i+1].f是大于q[i].f的所以我们根据这个性质 53 //我们每次在[0,q[i+1].f)这个区间里面去找第q[i].f+1大的的数 54 //我们还需要知道nth_element这个函数是把第n+1大的数放在n的下标里面 55 nth_element(num,num+q[i].first,num+q[i+1].first); 56 ans[q[i].second]=num[q[i].first]; 57 } 58 cout<<"Case #"<<++ca<<":"; 59 for(int i=0;i<m;i++) cout<<" "<<ans[i]; 60 cout<<endl; 61 } 62 return 0; 63 }