题目:点击打开链接
题意:输入五个数值:n,m,a,b,c
n的用处为:调用n次题中给出的函数,生成一个长为n的数列
m为m次查询,每次查数组a里第bi小的数
a,b,c即所给函数中的x,y,z初值
要求依次输出查到的数
思路:这里用到一个STL的nth_element(a,a+k,a+last),该函数可以使得第k大元素在k位置上(下标从0开始),并且把比该元素小的元素放前面,大的元素放后面,但是不是排好序的,也就是说前后部分还是乱序。
注意重点是题中的这一条件:bi+bj<=bk is satisfied if bi≠bj, bi<bk and bj<bk,这样的话就要把查询数组的查询次序进行排序,先查大的,cmp函数为return b[x]>b[y]。这样可以每次把nth函数的last迅速缩短,避免TLE。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e7+7;
int b[105],id[105];
unsigned a[maxn],ans[105];
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;
}
bool cmp(int x,int y)
{
return b[x]>b[y];
}
int main()
{
ll n,m;
int id[102];
int cas=0;
while(~scanf("%lld%lld%u%u%u",&n,&m,&x,&y,&z))
{
for(int i=0;i<n;i++)
a[i]=rng61();
for(int i=0;i<m;i++)
{
scanf("%d",&b[i]);
id[i]=i;
}
sort(id,id+m,cmp);
int p,last=n;
for(int i=0;i<m;i++)
{
p=id[i];
nth_element(a,a+b[p],a+last);
ans[p]=a[b[p]];
last=b[p];
}
printf("Case #%d: ",++cas);
for(int i=0;i<m-1;i++)
printf("%u ",ans[i]);
printf("%u\n",ans[m-1]);
}
return 0;
}