洛谷1309 瑞士輪 解題報告

2022-05-06 05:39:09 字數 3861 閱讀 9337

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

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題。

模擬+排序

這道題用樸素做法會超時,我們可以採用這樣的做法。

比賽用模擬的方法進行排序。

考慮到每個人的名次變動是有限的,對於所有在當前局比賽擊敗對手的人,他們的相對次序是不變的。

同樣,對於所有在當前局比賽輸給對手的人,他們的相對次序也是不變的。

所以我們可以用兩個佇列儲存贏和輸的人,能夠實現當局比賽o(n)的排序,即可在規定時間出解。

下面附上**。

var i1,i2,x,k,i,j,n,q,r,t,y,kmax,kmin,max,min:longint;      

b,num,num1,v,a:array[1..200000] of longint;      

procedure sort(l,r: longint);      

var      

i,j,x,y,x1: longint;      

begin      

i:=l;      

j:=r;      

x:=a[(l+r) div 2];      

x1:=num[(l+r) div 2];  

repeat      

while (a[i]>x) or (a[i]=x) and (num[i]do  

inc(i);      

while (x>a[j]) or (a[j]=x) and (num[j]>x1) do 

dec(j);      

if not(i>j) then      

begin        

y:=v[i];      

v[i]:=v[j];      

v[j]:=y;      

y:=a[i];      

a[i]:=a[j];      

a[j]:=y;

y:=num[i];    

num[i]:=num[j];      

num[j]:=y;      

inc(i);      

j:=j-1;      

end;      

until i>j;      

if lthen      

sort(l,j);      

if ithen      

sort(i,r);      

end;      

begin      

readln(n,r,q);      

for i:=1 to 2*n do      

begin      

read(a[i]);      

num[i]:=i;      

end;      

readln;      

sort(1,2*n);  

for i:=1 to 2*n do read(v[i]);      

for i:=1 to r do  

begin      

i1:=0; i2:=n;  

for j:=1 to n do      

begin      

if  v[num[j*2-1]]>v[num[j*2]] then  begin  max:=a[j*2-1]; min:=a[j*2];      

kmax:=j*2-1; kmin:=j*2      

end      

else  begin  max:=a[j*2]; min:=a[j*2-1];      

kmax:=j*2; kmin:=j*2-1;      

end;      

inc(i1); 

b[i1]:=max+1; num1[i1]:=num[kmax];      

inc(i2);      

b[i2]:=min;   num1[i2]:=num[kmin];      

end;      

x:=1;  y:=n+1;  k:=0;  

while (x<=n) and (y<=2*n) do      

begin      

if (b[x]>b[y]) or (b[x]=b[y]) and (num1[x]then 

begin

inc(k);      

a[k]:=b[x];      

num[k]:=num1[x];      

inc(x);      

end      

else begin inc(k);  a[k]:=b[y]; num[k]:=num1[y]; inc(y); end;      

end;      

if x<=n  then  for j:=x to n do  begin   inc(k);a[k]:=b[j]; num[k]:=num1[j] end;      

if y<=2*n then for j:=y to 2*n do begin inc(k);  a[k]:=b[j]; num[k]:=num1[j];  end;      

end;      

writeln(num[q]);      

end.    

洛谷 1309 瑞士輪

題目描述 2 n 名編號為 1 2n 的選手共進行r 輪比賽。每輪比賽開始前,以及所有比賽結束後,都會按照總分從高到低對選手進行一次排名。選手的總分為第一輪開始前的初始分數加上已參加過的所有比賽的得分和。總分相同的,約定編號較小的選手排名靠前。每輪比賽的對陣安排與該輪比賽開始前的排名有關 第1 名和...

洛谷1309 瑞士輪

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

洛谷1309 瑞士輪 題解

我覺得我大概已經是個zz了,普及題都不會做還得看題解,難受。o rnlogn 肯定過不了 過了也沒意義 複雜度能降下來肯定序列是有規律可循的。於是可以發現,勝者組和敗者組他們的s永遠都是單調減的。然後就把兩個有序的勝者組和敗者組合並就行了,和歸併排序差不多。我的智商已如風中殘燭。include in...