题解(54ms/56ms)(保姆级?)
2024-02-06 13:12:55
发布于:湖南
76阅读
0回复
0点赞
先读题:别看题目长的要*,实际上就是让我们模拟比赛,两两比拼,实力强的就得分+1,最后排序为下一轮比赛确定人员
首先由于初始分数可能不是有序的,所以需要把它变成有序的
接着重复r轮,每轮两两比较,实力强的分数加一,比较完sort一下就行了
快排解法(对应algorithm的sort)
快排就是定义一个枢轴,让每个元素和枢轴比较,使左半边小于(大于)右半边,然后划分成两半。
假设划分了一次,2半分别为A和B
则A中每个元素都小于B中每个元素
若再划分一次,分的四个部分分别为a, b, c, d
因为a, b分别是A的一部分,c, d分别是B的一部分
所以a, b中任何元素都小于c, d中任何元素
又因为a < b, c < d(此处指两部分任何一个元素的关系)
所以a < b < c < d.
最后细化到每个部分只代表一个元素,就可以使数组有序。
#include <iostream>
#include <cstdio>
//#include <algorithm>
using namespace std;
struct duiyuan{
int score, shili, id;
}a[200005];
bool cmp(duiyuan a, duiyuan b){//根据题意制作cmp
if(a.score == b.score){
return a.id < b.id;
}return a.score > b.score;
}
duiyuan midof3(duiyuan a, duiyuan b, duiyuan c){
if(cmp(b, a)) swap(a, b);
if(cmp(c, b)) swap(b, c);
if(cmp(b, a)) swap(a, b);
return b;//枢轴三数取中
}
int ptt(duiyuan *a, int left, int right){
int i = left, j = right;
duiyuan pivot = midof3(a[left], a[(left + right) / 2], a[right]);
while(1){
while(i < j && cmp(a[i], pivot)) i++;//指针扫描
while(i < j && cmp(pivot, a[j])) j--;
if(i >= j) return i;
swap(a[i], a[j]);//交换,使左半部分任意一个和右半部分任意一个cmp都返回1(相当于左半部分比右半部分小)
}
}
void sort(duiyuan *a, int left, int right){
if(left >= right){
return;
}
int i = ptt(a, left, right);
sort(a, left, i - 1);//划分
sort(a, i + 1, right); //此时我们可以保证枢轴单独是在正确的位置上
}
int main(){
int n, r, q;
cin >> n >> r >> q;
for(int i = 1; i <= 2 * n; i++){
cin >> a[i].score;
a[i].id = i;
}for(int i = 1; i <= 2 * n; i++){
cin >> a[i].shili;
}
sort(a, 1, 2 * n);//先排序一次
while(r--){
for(int i = 1; i <= n; i++){
if(a[i * 2 - 1].shili > a[i * 2].shili) a[i * 2 - 1].score++;//比较,赢的人得分+1
else a[i * 2].score++;
}
sort(a, 1, 2 * n);//排序
}cout << a[q].id;//输出
return 0;
}
时间复杂度:O(nlogn * r)
运行时间:54ms
但是,这些得分很多都是相同的,一个一个交换可能有点麻烦,所以归并排序也许会更快……
归并解法(对应algorithm的stable_sort)
归并,和名字一样,分为归和并两个步骤
归:用二分法把无序数组划分成若干个有序数组
并:把两个有序数组合并成一个有序数组
具体过程请看下面↓
1 2 9 2 9 9 9 9 9 9
1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 1 2 3 4 5 6 1 2 3 4 5 6 9
3 4 5 6 3 4 5 6 3 4 5 6 4 5 6 5 6 6
没错,就是把最前面的元素进行比较,哪个小(大)就拿出哪个放到另一个数组,然后把数组里的元素复制回去。
#include <iostream>
#include <cstdio>
//#include <algorithm>
using namespace std;
struct duiyuan{
int score, shili, id;
}a[200005], arr[200005];//先定义一个备用数组
int n, r, q;
bool cmp(duiyuan a, duiyuan b){//cmp
if(a.score == b.score){
return a.id < b.id;
}return a.score > b.score;
}
void merge(duiyuan *a, int left, int right){//并
int mid = (left + right) / 2;
int i = left, j = mid + 1, st = left - 1;
while(i <= mid && j <= right){
if(cmp(a[i], a[j])) arr[++st] = a[i++];//把数组最前面的元素进行比较,然后拿出来
else arr[++st] = a[j++];
}
while(i <= mid) arr[++st] = a[i++];//避免有漏的情况
while(j <= right) arr[++st] = a[j++];
for(int i = left; i <= right; i++){
a[i] = arr[i];//复制回去
}
}
void mergesort(duiyuan *a, int left, int right){//归
if(left >= right) return;
int mid = (left + right) / 2;
mergesort(a, left, mid);
mergesort(a, mid + 1, right);//二分法分割
merge(a, left, right);//合并
}
int main(){
int n, r, q;
cin >> n >> r >> q;
for(int i = 1; i <= 2 * n; i++){
cin >> a[i].score;
a[i].id = i;
}for(int i = 1; i <= 2 * n; i++){
cin >> a[i].shili;
}
mergesort(a, 1, 2 * n);//排序
while(r--){
for(int i = 1; i <= n; i++){
if(a[i * 2 - 1].shili > a[i * 2].shili) a[i * 2 - 1].score++;//加分
else a[i * 2].score++;
}
mergesort(a, 1, 2 * n);//排序
}
cout << a[q].id;
return 0;
}
时间复杂度:O(nlogn * r)
运行时间:56……ms?
完了翻车了
咳咳,反正代码就是这些,看完点个赞,我先溜了(
这里空空如也
有帮助,赞一个