2017 Multi-University Training Contest - Team 1—HDU6040

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

 

posted on 2017-07-30 20:07  xiaowuga  阅读(116)  评论(0编辑  收藏  举报

导航