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