HDU6040 Hints of sd0061

题目链接:https://vjudge.net/problem/HDU-6040

题目大意:

  给出 \(n\) 个数,有 \(m\) 次询问,每次询问这 \(n\) 个数中第 \(k+1\) 大的数是什么。

  另有附加限制:对于 \(n\) 个数中的任意三个数 \(a,b,c\),如果满足 \(a \not= b, a < c, b < c\),则有 \(a + b \le c\).

  \((1 \le n \le 10^{7}, 1 \le m \le 100)\)

解题思路:

  由附加限制不难联想到斐波那契数列,由于 \(F(36) = 14930352\),所以我们不难推测将这 \(m\) 次询问中去重后剩下的不同询问的个数是少于 \(36\) 的。

  在此,还要再介绍一个优秀的函数:nth_element. 其用法是:nth_element\((first, nth, last, compare)\);作用是:将第 \(n\) 大的元素放在位置 \(n\)(从0开始),处理完之后,默认排在它前面的元素都不比它大,排在它后面的元素都不比它小。如果有定义 \(compare()\) 函数的话,大小关系则由 \(compare()\) 定义。时间复杂度是 \(O(n)\).

  于是,一种优秀的做法是:将 \(m\) 个询问排序,去重,然后从大往小处理询问,用 nth_element() 求出区间第 \(k\) 大的数,并且将排在第 \(k\) 大的数后面的数都丢掉。

  最后,这是第 \(1000\) 题。悄悄地,为自己鼓个掌 \(XD\)

AC代码:

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 typedef long long LL;
 5 const LL MOD=1e9+7;
 6 const int MAXN=1e7+5;
 7 const int LIM=1e6;
 8 
 9 unsigned x,y,z;
10 unsigned rng61() {
11   unsigned t;
12   x ^= x << 16;
13   x ^= x >> 5;
14   x ^= x << 1;
15   t = x;
16   x = y;
17   y = z;
18   z = t ^ x ^ y;
19   return z;
20 }
21 int add,n;
22 unsigned a[MAXN],ta[MAXN];
23 struct ask{
24     int ind,pos;
25 }b[110];
26 bool cmp(const ask &x,const ask &y){
27     return x.ind<y.ind;
28 }
29 unsigned ans[110];
30 
31 int main(){
32 //    freopen("in.txt","r",stdin);
33     int m,kase=1;
34     unsigned A,B,C;
35     while(scanf("%d%d%u%u%u",&n,&m,&A,&B,&C)==5){
36         add=0;
37         x=A,y=B,z=C;
38         for(int i=0;i<n;i++)
39             a[i]=rng61();
40         for(int i=0;i<m;i++){
41             scanf("%d",&b[i].ind);
42             b[i].pos=i;
43         }
44         sort(b,b+m,cmp);
45         b[m].pos=m,b[m].ind=n;
46 
47         for(int i=m-1;i>=0;i--){
48             if(b[i].ind==b[i+1].ind)
49                 ans[b[i].pos]=ans[b[i+1].pos];
50             else{
51                 nth_element(a,a+b[i].ind,a+b[i+1].ind);
52                 ans[b[i].pos]=a[b[i].ind];
53             }
54         }
55         printf("Case #%d:",kase++);
56         for(int i=0;i<m;i++)    printf(" %u",ans[i]);
57         printf("\n");
58     }
59     return 0;
60 }

 

posted @ 2018-07-02 21:23  Blogggggg  阅读(214)  评论(0编辑  收藏  举报