瑞士輪(歸併)

2021-10-19 07:47:49 字數 1882 閱讀 6146

2*n名編號為1~2n的選手共進行r輪比賽。每輪比賽開始前,以及所有比賽結束後,都會對選手進行一次排名。排名的依據是選手的總分。選手的總分為第一輪開始前的初始分數加上已參加過的所有比賽的得分和。總分相同的,約定編號較小的選手排名靠前。

每輪比賽的對陣安排與該輪比賽開始前的排名有關:第1名和第2名、第3名和第4名、……、第2k – 1名和第2k名、…… 、第2n – 1名和第2n名,各進行一場比賽。每場比賽勝者得1分,負者得0分。也就是說除了首輪以外,其它輪比賽的安排均不能事先確定,而是要取決於選手在之前比賽中的表現。

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

輸入

輸入的第一行是三個正整數n、r、q,每兩個數之間用乙個空格隔開,表示有2*n名選手、r輪比賽,以及我們關心的名次q。

第二行是2*n個非負整數s1, s2, …, s2n,每兩個數之間用乙個空格隔開,其中si表示編號為i的選手的初始分數。

第三行是2*n個正整數w1, w2, …, w2n,每兩個數之間用乙個空格隔開,其中wi表示編號為i的選手的實力值。

輸出

輸出只有一行,包含乙個整數,即r輪比賽結束後,排名第q的選手的編號。

樣例輸入

2 4 2

7 6 6 7

10 5 20 15

樣例輸出

對於 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。

剛開始看到這題的時候肯定是想著用sort排,很簡單,但是提交上去就是超時,可能是因為數太多了,排的次數也多。

分析:分析之後不難發現,當每場比賽結束的時候,他們之間的順序是沒怎麼變化的,也就是說大致順序沒變,變的只是兩個之間或相鄰的前後幾個,那是否可以分別將勝者和負者各自存在乙個陣列裡,再將兩個陣列歸併呢?這樣時間複雜度是不是就減少很多了?

思路:在每場比賽後,將勝者和負者分別存進兩個陣列,再歸併;

accode:

#include

using namespace std;

int n,r,m;

const

int n=

200010

;struct ta[n]

,win[n]

,fa[n]

;int

cmp(t x,t y)

void

merge

(t a[n]

,t win[n]

,t f[n]

)//將兩個排序陣列歸併到乙個陣列裡;

else

if(win[i]

.sc.sc)

else

//分數相等,看編號;

else}}

while

(i<=n/2)

//剩下的存進去;

while

(j<=n/2)

}int

main()

else

}merge

(a,win,fa)

;//歸併win陣列,fa陣列到a陣列;

}//sort(a+1,a+1+n,cmp);

printf

("%d"

,a[m]

.id)

;return0;

}

如果對歸併不太熟的化建議看一下歸併排序的模板;

codevs1132 瑞士輪 歸併排序

分析 如果每次 n 100000 排序,共進行r輪 r n logn 50 100000 20 10 8,超時 第一次排序後 每次贏的和輸的隊伍分別有序,只需要 o n 的歸併排序,時間複雜度變為5 10 6,不再超時。include include sort using namespace std...

洛谷 P1309 瑞士輪(歸併)

題意 一共2n個人 有乙個初始分數 進行k輪比賽,每輪比賽按當前得分排出名次,然後比賽按照第1名和第2名,第3和第4 第2n 1和2n進行 實力各不相同且實力大的總能獲勝 獲勝方加一分,失敗方分數不變。思路 一開始想在每輪比賽前用sort排序,算了下複雜度大概o n n logn n k 顯然不行。...

P1309 瑞士輪 歸併排序

題目鏈結 題目背景 在雙人對決的競技性比賽,如桌球 羽毛球 西洋棋中,最常見的賽制是淘汰賽和迴圈賽。前者的特點是比賽場數少,每場都緊張刺激,但偶然性較高。後者的特點是較為公平,偶然性較低,但比賽過程往往十分冗長。本題中介紹的瑞士輪賽制,因最早使用於1895年在瑞士舉辦的西洋棋比賽而得名。它可以看作是...