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

题意:通过题目所给函数求出a数组,然后根据b数组排a数组。ai必须是a数组中第(bi+1)大的数。

解法:先通过下标对b数组排序。然后扫一遍b数组,如果相邻两个位置b相同,那么就还选上一个a(因为n可以小于m),所以可以多选。然后就可以利用快拍的思想来优化。因为是bi+1个数,所以可以把比a[bi+1]小的数放到左边,大的放在右边,这样下次扫b的时候只需要扫一边,这样优化就能过题了。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e7+7;
pair <unsigned, unsigned> p[102];
unsigned a[maxn];
int b[102], ans[102];
unsigned x, y, z;
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;
}
void qsort(int l, int r, int L, int R){
    if(l > r || L > R) return;
    if(l == r){
        for(int i=L; i<=R; i++){
            p[i].first = a[l];
        }
        return;
    }
    int i = l, j = r, val = a[(i+j)/2];
    do{
        while(a[i]<val) i++;
        while(a[j]>val) j--;
        if(i <= j){
            swap(a[i], a[j]);
            i++;
            j--;
        }
    }while(i<=j);
    int pos1 = upper_bound(b+L, b+R+1, j) - b;
    qsort(l, j, L, pos1-1);
    if(j + 2 == i){
        int mid = j + 1;
        int pos2 = upper_bound(b + L, b + R + 1, mid) - b;
        for(int x = pos1; x < pos2; x++){
            p[x].first = a[mid];
        }
        pos1 = pos2;
    }
    qsort(i, r, pos1, R);
}

int main()
{
    int n, m, ks = 0;
    while(~scanf("%d %d %u %u %u", &n,&m,&x,&y,&z))
    {
        for(int i=1; i<=n; i++){
            a[i] = rng61();
        }
        for(int i=1; i<=m; i++){
            scanf("%u", &p[i].first);
            p[i].first++;
            p[i].second = i;
        }
        sort(p+1, p+m+1);
        for(int i=1; i<=m; i++){
            b[i] = p[i].first;
        }
        qsort(1, n, 1, m);
        for(int i=1; i<=m; i++){
            ans[p[i].second] = p[i].first;
        }
        printf("Case #%d:", ++ks);
        for(int i=1; i<=m; i++){
            printf(" %u", ans[i]);
        }
        printf("\n");
    }
    return 0;
}