hdu 6040 Hints of sd0061(STL)

来源:互联网 发布:飞机大战java代码框架 编辑:程序博客网 时间:2024/06/09 14:05

Hints of sd0061

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2063    Accepted Submission(s): 612


Problem Description
sd0061, the legend of Beihang University ACM-ICPC Team, retired last year leaving a group of noobs. Noobs have no idea how to deal withm coming contests. sd0061 has left a set of hints for them.

There are
n noobs in the team, the i-th of which has a rating ai.sd0061 prepares one hint for each contest. The hint for the j-th contest is a number bj, which means that the noob with the (bj+1)-th lowest rating is ordained by sd0061 for the j-th contest.

The coach asks constroy to make a list of contestants. constroy looks into these hints and finds out:
bi+bjbk is satisfied if bibj,bi<bk and bj<bk.

Now, you are in charge of making the list for constroy.
 

Input
There are multiple test cases (about 10).

For each test case:

The first line contains five integers
n,m,A,B,C.(1n107,1m100)

The second line contains
m integers, the i-th of which is the number bi of the i-th hint. (0bi<n)

The
n noobs' ratings are obtained by calling following function n times, the i-th result of which is ai.

unsigned x = A, y = B, z = C;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;}
 

Output
For each test case, output "Case #x:y1y2ym" in one line (without quotes), where x indicates the case number starting from 1 and yi(1im) denotes the rating of noob for the i-th contest of corresponding case.
 

Sample Input
3 3 1 1 10 1 22 2 2 2 21 1
 

Sample Output
Case #1: 1 1 202755
Case #2: 405510 405510


题意:
每次根据b数组来a数组里面第bi+1小的数,a数组可以循环执行所给函数n次来得到

解析:
 因为题目数据量比较大,时间有卡的比较紧,所以一个个排序是不现实的,我们只需要知道每次第bi+1个小的数,刚好C++里面有一个nth_element(first,nth,last,compare),first代表数据开头位置,nth表示你所要找的第n个小(大)的数,last表示数据结尾位置,compare表示比较函数。
这里因为数据太大每一次last设为a+n是不现实的,nth_element()这个函数的实现其实是将比第n个小的数小的数放在n的左边,比第n个小的数大的放在n的右边,然后将第n个小的书放在n这个位置。这样的话就可以将b数组从大到小排序,当大数得到对应值时,我们就可以缩小区间(因为剩余数都小于这个数,所以剩余数的答案(第剩余数个小的数)肯定在大数的一侧区间内)
这样之后你可能还会TLE,剩下的就全靠人品了,多是几次应该就可以了,我交了4次只在第2次过了


#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#define MAXN 10000010using namespace std;typedef  struct node{int num;int hin;}node;node hint[201];unsigned ans[201];unsigned x,y,z,rate[MAXN],A,B,C;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;}int cmp(unsigned a,unsigned b){return a<b;}int cmp1(node a,node b){return a.hin>b.hin;}/*int cmp2(node a,node b){return a.num<b.num;}*/int main(){int n,m,t;t=0;while(scanf("%d%d%u%u%u",&n,&m,&A,&B,&C)!=EOF){t++;for(int i=0;i<m;i++){scanf("%d",&hint[i].hin);hint[i].num=i;}sort(hint,hint+m,cmp1);x=A;y=B;z=C;for(int i=0;i<n;i++){rate[i]=rng61();}int right=n;for(int i=0;i<m;i++){nth_element(rate,rate+hint[i].hin,rate+right,cmp);ans[hint[i].num]=rate[hint[i].hin];right=hint[i].hin;}//sort(hint,hint+m,cmp2);printf("Case #%d: ",t);for(int i=0;i<m;i++){if(i==m-1)printf("%u\n",ans[i]);else printf("%u ",ans[i]);}}return 0;}







原创粉丝点击