洛谷P1309 瑞士轮 【归并排序】

题目链接:P1309 瑞士轮

程序说明:

卡了一个晚上,思路比较简单但是细节很多,有很多大坑!
每轮比赛结束后都需要对选手的成绩进行排序,这道题不能用STL的sort()或者手写快排进行排序,否则会超时(除非开o2优化)。看了题解之后才知道要用归并排序,于是手写归并结果还是超时。其实是没有掌握到归并的精髓。

这道题并不需要把归并排序的完整过程写出来(比如递归什么的…),否则和快排就一样了仍然会超时。需要额外开两个数组,每次比赛后,赢的人到x数组,输的人到y数组,这样的话仍然能保证x数组和y数组分别有序,因此只需要进行归并操作就可以了(即双指针)。

不开o2就能ac的代码如下:

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
//注意数组大小是2 * n 
const int N = 200010;
int n, r, q;
struct node {
	int num; //序号 
	int score; //分数 
	int weight; //权值 
} a[N], x[N], y[N]; 
bool cmp(node a, node b) {
	if(a.score == b.score) return a.num < b.num;
	return a.score > b.score;
}
//归并操作 
void merge_sort() {	
	int i = 1, j = 1, k = 1;
	while(i <= n && j <= n) {
		if(x[i].score > y[j].score || x[i].score == y[j].score && x[i].num < y[j].num)
			a[k++] = x[i++];
		else a[k++] = y[j++];
	}
	while(i <= n) a[k++] = x[i++];
	while(j <= n) a[k++] = y[j++];
}

int main() {
	//freopen("D://a.txt", "r", stdin); 
	scanf("%d%d%d", &n, &r, &q);
	for(int i = 1; i <= n * 2; i++) {
		scanf("%d", &a[i].score);
		a[i].num = i;
	}
	for(int i = 1; i <= n * 2; i++) {
		scanf("%d", &a[i].weight);
	}
	sort(a + 1, a + n * 2 + 1, cmp);
	
	for(int i = 1; i <= r; i++) {
		int k = 1;
		for(int j = 1; j <= n * 2 - 1; j += 2) { //注意j是奇数 
			if(a[j].weight < a[j + 1].weight) {
				a[j + 1].score++;
				x[k] = a[j + 1];
				y[k] = a[j];
				k++;
			}
			else {
				a[j].score++;
				x[k] = a[j];
				y[k] = a[j + 1];
				k++;
			} 
				
		}		
		merge_sort();
	}
	printf("%d", a[q].num);
	//fclose(stdin);
	return 0;
} 
发布了47 篇原创文章 · 获赞 0 · 访问量 1273

猜你喜欢

转载自blog.csdn.net/Komatsu_1137/article/details/104112242
今日推荐