题意:通过题目所给函数求出a数组,然后根据b数组排a数组。ai必须是a数组中第(bi+1)大的数。
分析:先通过下标对b数组排序。然后扫一遍b数组,如果相邻两个位置b相同,那么就还选上一个a(因为n可以小于m),所以可以多选。然后就可以利用快拍的思想来优化。因为是bi+1个数,所以可以把比a[bi+1]小的数放到左边,大的放在右边,这样下次扫b的时候只需要扫一边,这样优化就能过题了。
注意
因为输入保证任意两个小的之和小于第三个
所以查询数列的间隔一定大于等于斐波那契
也就是从大到小查询的话,每次至少能去掉一半的区间
#include<bits/stdc++.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define nl n<<1
#define nr (n<<1)1
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f;
const ll INFF=0x3f3f3f3f3f3f3f3f;
const double pi=acos(-1.0);
const double eps=1e-9;
const ll mod=1e9+7;
unsigned int a[10000010];
unsigned int x,y,z;
unsigned int rng61()
{
unsigned int t;
x ^= x << 16;
x ^= x >> 5;
x ^= x << 1;
t = x;
x = y;
y = z;
z = t ^ x ^ y;
return z;
}
int b[105];
int n,m,pos[105];
unsigned int ans[105];
bool cmp(int x,int y)
{
return b[x]<b[y];
}
int main()
{
int v=1;
while(scanf("%d%d%u%u%u",&n,&m,&x,&y,&z)!=EOF)
{
for(int i=0;i<m;i++)
{
scanf("%d",&b[i]);
pos[i]=i;
}
sort(pos,pos+m,cmp);//通过b的大小对下标排序。
for(int i=0;i<n;i++)
{
a[i]=rng61();
}
b[pos[m]=m]=n;
for(int i=m-1;i>=0;i--)
{
if(b[pos[i]]==b[pos[i+1]])
{
ans[pos[i]]=ans[pos[i+1]];
continue;
}
nth_element(a,a+b[pos[i]],a+b[pos[i+1]]);//将a数组第b[pos[i]]小的数放到数组左边,比他大的放到数组右边
ans[pos[i]]=a[b[pos[i]]];
}
printf("Case #%d:",v++);
for(int i=0;i<m;i++)
{
printf(" %u",ans[i]);
}
printf("\n");
}
return 0;
}
//
int a[]={13,67,34,123,4,56,7,9,12,23};
nth_element(a,a+5,a+10);
for(int i=0;i<10;i++)
{
printf("%d ",a[i]);//9 7 4 13 12 23 34 56 123 67
}
//+5,就是起码有5个比他小的数!