標籤:
題目描述 Description
背景
在雙人對決的競技性比賽,如乒乓球、羽毛球、國際象棋中,最常見的賽制是淘汰賽和迴圈賽。前者的特點是比賽場數少,每場都緊張刺激,但偶然性較高。後者的特點是較為公平,偶然性較低,但比賽過程往往十分冗長。
本題中介紹的瑞士輪賽制,因最早使用於 1895 年在瑞士舉辦的國際象棋比賽而得名。它可以看作是淘汰賽與迴圈賽的折衷,既保證了比賽的穩定性,又能使賽程不至於過長。
2*N 名編號為1~2N 的選手共進行R 輪比賽。每輪比賽開始前,以及所有比賽結束後,都會按照總分從高到低對選手進行一次排名。選手的總分為第一輪開始前的初始分數加上已參加過的所有比賽的得分和。總分相同的,約定編號較小的選手排名靠前。每輪比賽的對陣安排與該輪比賽開始前的排名有關:第 1 名和第2 名、第3 名和第4名、……、第2K – 1 名和第2K 名、…… 、第 2N – 1 名和第2N 名,各進行一場比賽。每場比賽勝者得1 分,負者得0 分。也就是說除了首輪以外,其它輪比賽的安排均不能事先確定,而是要取決於選手在之前比賽中的表現。
現給定每個選手的初始分數及其實力值,試計算在 R 輪比賽過後,排名第Q 的選手編號是多少。我們假設選手的實力值兩兩不同,且每場比賽中實力值較高的總能獲勝。
輸入描述 Input Description
輸入的第一行是三個正整數 N、R、Q,每兩個數之間用一個空格隔開,表示有2*N 名選手、R 輪比賽,以及我們關心的名次Q。
第二行是 2*N 個非負整數s1, s2, …, s2N,每兩個數之間用一個空格隔開,其中si 表示編號為i 的選手的初始分數。
第三行是 2*N 個正整數w1, w2, …, w2N,每兩個數之間用一個空格隔開,其中wi 表示編號為i 的選手的實力值。
輸出描述 Output Description
輸出只有一行,包含一個整數,即 R 輪比賽結束後,排名第Q 的選手的編號。
範例輸入 Sample Input
2 4 2
7 6 6 7
10 5 20 15
範例輸出 Sample Output
1
資料範圍及提示 Data Size & Hint
資料範圍
對於 30%的資料,1 ≤ N≤ 100;
對於 50%的資料,1 ≤ N≤ 10,000;
對於 100%的資料,1 ≤ N≤ 100,000,1 ≤ R≤ 50,1 ≤ Q≤ 2N,0 ≤ s1, s2, …, s2N ≤ 108,1 ≤ w1,w2, …, w2N ≤ 108。
解題思路
關於這個題……我只想笑笑不說話,第一次做這個題我果斷選擇r次快排,然後果斷拿個50分,後來童鞋們告訴我,只需要建立兩個數組,一個儲存加分,一個儲存不加分,在然後歸併排序,把原來O(nlogn)的複雜度降到O(n),就可以輕鬆卡過最大值。再然後我順利的敲出了代碼,後來調試不過!!!這又是為什麼呢?在經過艱苦卓絕的n遍調試之後我發現我的歸併排序並沒有把沒有把沒有在迴圈中進入原數組的值重新帶回去,導致了錯誤!!!一定要在看一遍歸併排序!!!
program Swiss;type peo=record w,s,no:longint; end;var pe:array[0..200000] of peo; w,f:array[1..200000] of peo; n,r,q1,i,j,sum:longint;procedure sort(l,r: longint);//多關鍵字快排 var i,j,x,y: longint; begin i:=l; j:=r; x:=pe[(l+r) div 2].s; y:=pe[(l+r) div 2].no; repeat while (pe[i].s>x) or ((x=pe[i].s) and (y>pe[i].no))do inc(i); while (x>pe[j].s) or ((x=pe[j].s) and (y<pe[j].no)) do dec(j); if not(i>j) then begin pe[0]:=pe[i]; pe[i]:=pe[j]; pe[j]:=pe[0]; inc(i); j:=j-1; end; until i>j; if l<j then sort(l,j); if i<r then sort(i,r); end;procedure guibing;//歸併var q,p,sum1,k:longint;begin q:=1; p:=1; sum1:=0; while (q<=n) and (p<=n) do begin if (w[q].s>f[p].s) or ((w[q].s=f[P].s) and (w[q].no<f[p].no)) then begin inc(sum1); pe[sum1]:=w[q]; inc(q); end; if (w[q].s<f[p].s) or ((w[q].s=f[P].s) and (w[q].no>f[p].no)) then begin inc(sum1); pe[sum1]:=f[p]; inc(p); end; end; if q=n+1 then//錯在這裡真丟人 for k:=p to n do begin inc(sum1); pe[sum1]:=f[k]; end else for k:=q to n do begin inc(sum1); pe[sum1]:=w[k]; end;end;begin read(n,r,q1); for i:=1 to 2*n do pe[i].no:=i; for i:=1 to 2*n do read(pe[i].s); for i:=1 to 2*n do read(pe[i].w); sort(1,2*n); pe[0].no:=0; for j:=1 to r do begin i:=1; sum:=0; while i<=2*n do begin inc(sum); if pe[i].w>pe[i+1].w then begin inc(pe[i].s); w[sum]:=pe[i]; f[sum]:=pe[i+1]; end else begin inc(pe[i+1].s); w[sum]:=pe[i+1]; f[sum]:=pe[i]; end; i:=i+2; end; guibing; end; writeln(pe[q1].no);end.
CODEVS 1132 瑞士輪