洛谷瑞士輪---合併排序

洛谷瑞士輪—合併排序

在雙人對決的競技性比賽,如乒乓球、羽毛球、國際象棋中,最常見的賽制是淘汰賽和循環賽。
前者的特點是比賽場數少,每場都緊張刺激,但偶然性較高。後者的特點是較爲公平,偶然性較低,但比賽過程往往十分冗長。
本題中介紹的瑞士輪賽制,因最早使用於1895年在瑞士舉辦的國際象棋比賽而得名。
它可以看作是淘汰賽與循環賽的折中,既保證了比賽的穩定性,又能使賽程不至於過長。

題目描述
2*N 名編號爲 1~2N 的選手共進行R 輪比賽。每輪比賽開始前,以及所有比賽結束後,
都會按照總分從高到低對選手進行一次排名。選手的總分爲第一輪開始前的初始分數加上已參加過的所有比賽的得分和。
總分相同的,約定編號較小的選手排名靠前。
每輪比賽的對陣安排與該輪比賽開始前的排名有關:第1 名和第2 名、第 3 名和第 4名、……、第2K – 1 名和第 2K名、…… 、
第2N – 1 名和第2N名,各進行一場比賽。每場比賽勝者得1 分,負者得 0 分。也就是說除了首輪以外,
其它輪比賽的安排均不能事先確定,而是要取決於選手在之前比賽中的表現。
現給定每個選手的初始分數及其實力值,試計算在R 輪比賽過後,排名第 Q 的選手編號是多少。
我們假設選手的實力值兩兩不同,且每場比賽中實力值較高的總能獲勝。
輸入輸出格式
輸入格式:
輸入文件名爲swiss.in 。
輸入的第一行是三個正整數N、R 、Q,每兩個數之間用一個空格隔開,表示有 2*N 名選手、R 輪比賽,以及我們關心的名次 Q。
第二行是2*N 個非負整數s1, s2, …, s2N,每兩個數之間用一個空格隔開,其中 si 表示編號爲i 的選手的初始分數。
第三行是2*N 個正整數w1 , w2 , …, w2N,每兩個數之間用一個空格隔開,其中 wi 表示編號爲i 的選手的實力值。
輸出格式:
輸出文件名爲swiss.out。
輸出只有一行,包含一個整數,即R 輪比賽結束後,排名第 Q 的選手的編號。
輸入輸出樣例
輸入樣例#1: 複製
2 4 2
7 6 6 7
10 5 20 15
輸出樣例#1: 複製
1
說明
對於30% 的數據,1 ≤ N ≤ 100;
對於50% 的數據,1 ≤ N ≤ 10,000 ;
對於100%的數據,1 ≤ N ≤ 100,000,1 ≤ R ≤ 50,1 ≤ Q ≤ 2N,0 ≤ s1, s2, …, s2N≤10^8,1 ≤w1, w2 , …, w2N≤ 10^8。
noip2011普及組第3題。

解題思路
1.通過對時間複雜度的分析可以看出利用快排超時
2.根據題目的特點來看,排序時只要合併兩個有序表就可以
3.因爲每次比賽完,輸贏兩方本來就是有序的
4.即使有一小部分數據無序也不算很影響總體的
5.merge函數的應用
6.vector的應用,注意不能直接用下標,要用at
7.注意排序前分配大小resize和清空clear

//merge函數的作用是:將兩個有序的序列合併爲一個有序的序列。
//函數參數:merge(first1,last1,first2,last2,result,compare);
//firs1t爲第一個容器的首迭代器,last1爲第一個容器的末迭代器
//first2爲第二個容器的首迭代器,last2爲容器的末迭代器,
//result爲存放結果的容器,comapre爲比較函數(可略寫,默認爲合併爲一個升序序列)。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
typedef struct node {
    int i;//編號
    int s;//分數
    int w;//實力
} Node;
Node a[200010];
vector<Node>A;
vector<Node>B;
vector<Node>C;
bool cmp(Node x,Node y) {
    if(x.s==y.s) {
        return x.i<y.i;
    }
    return x.s>y.s;
}
int main() {
    int n,r,q;
    memset(a,0,sizeof(a));
    cin>>n>>r>>q;
    for(int i=0; i<2*n; i++) {
        a[i].i=i;
        scanf("%d",&a[i].s);
    }
    for(int i=0; i<2*n; i++) {
        scanf("%d",&a[i].w);
    }
    sort(a,a+2*n,cmp);
    for(int j=0; j<2*n-1; j+=2) {
        if(a[j].w<a[j+1].w) {
            a[j+1].s++;
            A.push_back(a[j+1]);
            B.push_back(a[j]);
        } else {
            a[j].s++;
            A.push_back(a[j]);
            B.push_back(a[j+1]);
        }
    }
    C.resize(200010);//必須分配大小
    merge(A.begin(),A.end(),B.begin(),B.end(),C.begin(),cmp);
    for(int i=1; i<r; i++) {
        A.clear();
        B.clear();
        for(int j=0; j<2*n-1; j+=2) {
            if(C.at(j).w<C.at(j+1).w) {
                C.at(j+1).s++;
                A.push_back(C.at(j+1));
                B.push_back(C.at(j));
            }
            else {
                C.at(j).s++;
                A.push_back(C.at(j));
                B.push_back(C.at(j+1));
            }
        }
        C.clear();
        C.resize(200010);
        merge(A.begin(),A.end(),B.begin(),B.end(),C.begin(),cmp);
    }
    cout<<C.at(q-1).i+1<<endl;
    return 0;
}
發佈了29 篇原創文章 · 獲贊 11 · 訪問量 9279
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章