Noip—p1309 瑞士轮

题目描述:洛谷p1309瑞士轮题目描述放在链接里,忘记题目描述的同学可以回去复习一下嗷。
思路 看了好多题解,都是硬往归并排序上靠,但是为什么是归并排序呢,看了好多篇文章都没有看懂,直到我手动的去模拟了一次,所以这道题它并不是单纯的归并排序,而是模拟归并排序(如果不会归并排序的小伙伴,可以看一下我的博客归并排序)。为什么这么说呢?因为每进行一场比赛,都要根据选手实力分出胜者组和败者组,然后我们再将胜者组和败者组根据分数大小来排成新的序列,依次类推。是不是突然感觉像归并排序中的先二分分裂,再回溯合并的过程,二分分裂是单纯的使用序列的长度进行分裂,但是在这道题中我们需要用选所受的实力,分为胜败者组,所以我觉得这道题的本质仍然是模拟,模拟的像归并排序,需要注意的是第一次我们得sort一下,因为第一场的顺序是我们没法提前预知的。
注意:不能够直接进行一轮比赛去sort()一次,时间会爆炸的,sort()对随机数组的排序比较快速且重复较少。
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
struct node
{
    int num;
    int s;
    int w;
};
node vis[N],tmp[N],win[N],lose[N];
int n,r,q;
bool cmp(node s1,node s2)
{
    if(s1.s==s2.s)return s1.num<s2.num;
    else return s1.s>s2.s;
}
void solve()
{
    int wi=1,li=1;
    for(int i=1;i<=n*2;i=i+2)
    {
        if(vis[i].w>vis[i+1].w)
        {
            vis[i].s++;
            win[wi++]=vis[i];
            lose[li++]=vis[i+1];
        }
        else
        {
            vis[i+1].s++;
            win[wi++]=vis[i+1];
            lose[li++]=vis[i];
        }
    }
    int i=1,j=1,k=1;
    while(i<wi&&j<li)
    {
        if(cmp(win[i],lose[j]))
        {
            vis[k++]=win[i++];
        }
        else vis[k++]=lose[j++];
    }
    while(i<wi)vis[k++]=win[i++];
    while(j<li)vis[k++]=lose[j++];
   // for(i=1;i<=n;i++)vis[i]=tmp[i];
}
int main()
{
    cin>>n>>r>>q;
    for(int i=1;i<=n*2;i++)
    {
        cin>>vis[i].s;
        vis[i].num=i;
    }
    for(int i=1;i<=n*2;i++)cin>>vis[i].w;
    sort(vis+1,vis+1+2*n,cmp);
    for(int i=1;i<=r;i++)
    {
        solve();
    }
    //for(int i=1;i<=n*2;i++)printf("%d***%d\n",vis[i].num,vis[i].s);
    //printf("\n");
    printf("%d",vis[q].num);
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值