hdu 6040 Hints of sd0061(STL)

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 with m 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 : y1 y2 ym " 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 1 0 1 2 2 2 2 2 2 1 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 10000010
using 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;
}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值