0720-归并排序-noip 2011 瑞士轮


题解

这真的是一道很简单的模拟题啊,随便模拟一下就可以了,按照题目意思一步步敲出代码,60分就到手了

那怎么得到100分呢?

首先我们要知道只得60分是因为 T 了4组,那么是哪里重复计算(或其他什么毛病)导致时间T掉呢。

很显然是 sort 排序拖了后腿,因为其时间复杂度为n log(n)。那我们就需要另辟蹊径,找其他的排序方法,而归并排序就很符合这道题,其复杂度为O (n+m)的,又由于归并排序是对于两个有序数列干的事,所以我们要稍微处理一下,用空间去换时间

在每次操作时,赢的人和输的人分开装,然后归并就可以了


代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 200009
using namespace std;
long long n,r,q;
int tl,tw;
inline long long read(){
	char ch;int f=1;
	while((ch=getchar())<'0'||ch>'9')
		if(ch=='-') f=-1;
	long long res=0;
	while(ch>='0'&&ch<='9'){
		res=res*10+ch-'0';
		ch=getchar();
	}
	return f*res;
}
struct node{
	long long s,w;
	int id;
}a[N],w[N],l[N];
bool cmp(const node &a,const node &b){
	if(a.s>b.s) return 1;
	if(a.s<b.s) return 0;
	if(a.id<b.id) return 1;
	return 0;
}
void merge_h(){
	int i=1,j=1,tot=0;
	while(i<=tw&&j<=tl){
		if(cmp(w[i],l[j])) a[++tot]=w[i++];
		else a[++tot]=l[j++];
	}
	if(i<=tw){
		for(int k=i;k<=tw;++k)
			a[++tot]=w[k];
	}
	else
		for(int k=j;k<=tl;++k)
			a[++tot]=l[k];
}
int main()
{
	n=read();r=read();q=read();
	int i,j,k;
	n=2*n;
	for(i=1;i<=n;++i){
		a[i].s=read();
		a[i].id=i;
	}
	for(i=1;i<=n;++i)
		a[i].w=read();
	sort(a+1,a+n+1,cmp);
	for(int tt=1;tt<=r;++tt){
		tw=0;tl=0;
		for(i=1;i<=n;i+=2){
			if(a[i].w>a[i+1].w) a[i].s++,w[++tw]=a[i],l[++tl]=a[i+1];
			else a[i+1].s++,w[++tw]=a[i+1],l[++tl]=a[i];
		}
		merge_h();//归并
	}
	printf("%d",a[q].id);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42557561/article/details/81133908
今日推荐