瑞士輪 洛谷 歸併

題目描述
2*N 名編號爲 1~2N 的選手共進行R 輪比賽。每輪比賽開始前,以及所有比賽結束後,都會按照總分從高到低對選手進行一次排名。選手的總分爲第一輪開始前的初始分數加上已參加過的所有比賽的得分和。總分相同的,約定編號較小的選手排名靠前。
每輪比賽的對陣安排與該輪比賽開始前的排名有關:第1 名和第2 名、第 3 名和第 4名、……、第2K – 1 名和第 2K名、…… 、第2N – 1 名和第2N名,各進行一場比賽。每場比賽勝者得1 分,負者得 0 分。也就是說除了首輪以外,其它輪比賽的安排均不能事先確定,而是要取決於選手在之前比賽中的表現。

現給定每個選手的初始分數及其實力值,試計算在R 輪比賽過後,排名第 Q 的選手編號是多少。我們假設選手的實力值兩兩不同,且每場比賽中實力值較高的總能獲勝。

void merge(int l,int r)
{
    if(l==r)return 0;
    int mid=(l+r)/2;
    merge(l,mid);
    merge(mid+1,r);
    int i=l,j=mid+1,p=l;
    while(i<=mid&&j<=r)
    {
        if(a[i]>a[j])temp[++p]=a[++i];
        else temp[++p]=a[++j];
    }
    while(i<=mid)temp[++p]=a[++i];
    while(j<=r)temp[++p]=a[++j];
    for(int i=l;i<=r;i++)a[i]=temp[i];
}
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
typedef long long LL;
int n,r,q;
int a[200100],win[200100],lose[200100];
int s[200100],w[200100];
bool cmp(int x,int y)
{
    if(s[x]==s[y])   return x<y;
    return s[x]>s[y];
}
void merge()
{
    int i,j;
    i=j=1,a[0]=0;
    while(i<=win[0] && j<=lose[0])
        if(cmp(win[i],lose[j]))
            a[++a[0]]=win[i++];
        else
            a[++a[0]]=lose[j++];
    while(i<=win[0])a[++a[0]]=win[i++];
    while(j<=lose[0])a[++a[0]]=lose[j++];
}
int main()
{
    cin>>n>>r>>q;
    n*=2;
    for(int i=1; i<=n; i++)a[i]=i;
    for(int i=1; i<=n; i++)cin>>s[i];
    for(int i=1; i<=n; i++)cin>>w[i];
    sort(a+1,a+n+1,cmp);
    for(int i=1; i<=r; i++)
    {
        win[0]=lose[0]=0;
        for(int j=1; j<=n; j+=2)
            if(w[a[j]]>w[a[j+1]])
            {
                s[a[j]]++;
                win[++win[0]]=a[j];
                lose[++lose[0]]=a[j+1];
            }
            else
            {
                s[a[j+1]]++;
                win[++win[0]]=a[j+1];
                lose[++lose[0]]=a[j];
            }
        merge();
    }
    cout<<a[q];
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章