题解(147ms)(保姆级)
2024-01-31 23:02:21
发布于:湖南
一般解法:先排序一次,然后重复r次:两两比较,把赢的人得分+1,最后排序。
代码:
欸嘿不给你看,去削弱版看我
时间复杂度:O(nlogn * r) (实际上n代表2n,但常数项省略)
最高运行时间:700ms左右✔(由于数组重复元素较多所以建议用stable_sort可以控制在600ms以下)
但是你放进洛谷里测:怎么两个TLE啊啊啊啊啊啊谁设的500ms啊啊啊啊啊啊啊
有没有优化的方法???
答案是肯定的!!!
我们仔细思考🤔:首先这个序列排序后得分是有序的,如果按顺序把赢了的和输了的分开是不是也是有序的?
举个例子:
原来排序后的得分是
8 8 7 7 7 6 6 5
假设按赢了和输了的分开后每个数组的队员得分分别为
8 7 7 6
8 7 6 5
是不是有序的?
如果你怀疑的话,你可以多实验几次(
然后我们把赢了的队员全部加1分(实际上在进行分输赢时就可以加),由于加的数值是相同的,所以就算加一亿分都是有序(不考虑爆int)
知道了这个,接着怎么做?
归并排序学过吗?
没学过也不用担心!网上搜
其中最终要的一步之一好吧本身也就只有两步就是“并”
所谓并,就是把两个有序数组合并成一个
具体过程:把最前面的元素进行比较,哪个小(大)就拿哪个,然后进行下一轮比较
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
懂了吗?本来归并排序还有归的操作,是为了原来的无序数组要划分成无数个有序数组来合并
但是——因为只有两个有序数组需要排序,所以省去了很多小并,只剩下了一个大并(
一次大并的时间复杂度为O(n),按照题目重复r次,所以本题解时间复杂度就为O(n * r)了
废话不多说,下↓
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
struct duiyuan{
int score, shili, id;
}a[200005], win[100005], lose[100005];//
int n, r, q, ct;
bool cmp(duiyuan a, duiyuan b){
if(a.score == b.score){
return a.id < b.id;
}return a.score > b.score;
}
void merge(duiyuan *a, duiyuan *b, duiyuan *c, int len){//并
int ct = 1, i = 1, j = 1;
while(i <= len && j <= len){
if(cmp(b[i], c[j])) a[ct++] = b[i++];//一个一个比较,满足cmp的放进去
else a[ct++] = c[j++];
}while(i <= len) a[ct++] = b[i++];//避免漏掉
while(j <= len) a[ct++] = c[j++];
}
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, a + 2 * n + 1, cmp);//先排序一次
while(r--){
ct = 0;
for(int i = 1; i <= n; i++){
if(a[2 * i - 1].shili > a[2 * i].shili) win[++ct] = {a[2 * i - 1].score + 1, a[2 * i - 1].shili, a[2 * i - 1].id}, lose[ct] = a[2 * i];//本来这个也写了个函数的,但是发电删掉了,这段代码简单来说就是把赢的得分加一放进赢的,输的放进输的
else win[++ct] = {a[2 * i].score + 1, a[2 * i].shili, a[2 * i].id}, lose[ct] = a[2 * i - 1];
}
merge(a, win, lose, ct);//并
}
cout << a[q].id;//输出
return 0;
}
时间复杂度:O(n * r)
最高运行时间:147ms😎
不要CV球球了啊啊啊啊啊主要了解思路
看到了点个赞呗,第一次写这么长的题解qwq
全部评论 3
我不回我不会!
2024-07-25 来自 广东
0最简单的办法就是比完赛赢得加一分,然后sort
2024-07-25 来自 湖南
0#include <bits/stdc++.h> #define ll long long using namespace std; const int N=1e6+10; int n,r,q,ct; int read(){ int x=0,f=1; char ch=getchar(); while(ch<'0' or ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' and ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x*f; } void write(int x){ if(x>9) write(x/10); putchar(x%10+'0'); } struct player{ int id,score,liliang; }a[N],win[N],lose[N]; bool compare(player one,player two){ if(one.score!=two.score) return one.score>two.score; return one.id<two.id; } void merge(player *a,player *b,player *c,int n){ int i=1; int j=1; int l=1; while(i<=n and j<=n){ if(compare(b[i],c[j])) a[l++]=b[i++]; else a[l++]=c[j++]; } while(i<=n) a[l++]=b[i++]; while(j<=n) a[l++]=c[j++]; } int main(){ n=read(); r=read(); q=read(); vector<player>players(2*n); for(int i=0;i<n*2;++i){ players[i].score=read(); players[i].id=i+1; } for(int i=0;i<2*n;++i){ players[i].liliang=read(); } sort(a,a+2*n,compare); while(r--){ ct=0; for(int i=0;i<2*n;++i){ if(a[2*i-1].liliang>a[2*i].liliang){ win[++ct]={a[2*i-1].score+1,a[2*i-1].liliang,a[2*i-1].id}; lose[ct]=a[2*i]; } else { win[++ct]={a[2*i].score+1,a[2*i].liliang,a[2*i].id}; lose[ct]=a[2*i-1]; } } merge(a,win,lose,ct); } write(a[q].id); }
2024-07-25 来自 广东
0
啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊我要发电
2024-01-30 来自 湖南
0快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的快看我的
2024-01-29 来自 湖南
0
有帮助,赞一个