スイス] [NOIPラウンド
トピックの背景
このよう卓球、バドミントン、チェスのように競争力のあるゲーム、の二重の決闘では、ゲームシステムは、最も一般的なノックアウトラウンドロビンです。前者は競技場の数が少ない、エキサイティングなすべてのゲームが、より高いチャンスが特徴です。後者は比較的公正、低偶然ことを特徴としているが、レースは、多くの場合、非常に長いです。
この問題は、名前の18951895にスイスで開催された最初のチェスのトーナメントの使用に、スイスラウンドゲームシステムに記述されています。これは、ゲームの安定性を確保するだけでなく、レースが長すぎることはないだろうにするために、両方の、ノックアウトラウンドロビンとの妥協点として見ることができます。
タイトル説明
2×N数1〜2Nの選手は、Rラウンドの合計でした。各ラウンドの開始、およびすべてのゲームの終了前に、プレイヤーは降順のランクを追跡するためにアウトになります。最初のプレイヤーの合計スコアが最初のラウンドの開始前に、スコアであるとすべての競技や得点に参加しています。同じスコア、小さい選手のランキングの合意数。
ラウンドのトップと各ラウンドが始まっについて手配に対して:第一及び第二、第三及び第四、......、最初の2K-1および第2K名、......、最初に2N-1名と2N最初の名前は、ゲームのための各。すべてのゲームの勝者は、敗者00ポイントを1ポイントを取得します。それは最初のラウンドに追加され、配置の別のラウンドは、事前に決定することはできませんが、試合前に選手たちのパフォーマンスに依存します。
今ラウンド後にスコア及び各プレーヤーの強度計算のRの初期値を与え、プレイヤは、番号QQ番号がどのくらいであるランク付けしました。私たちは、すべてのゲームでは、プレイヤーの強さのペアごとにばらばらの値、および高強度の値が常に優先することを前提としています。
入力形式
最初の3行は、正の整数N、R、Q、二つの数字の間の空間によって分離され、それぞれが、2×Nは、プレイヤー、Rラウンドを表し、我々が懸念及びランクQ.されているがされています
2行目は、2×N個の各2つの数の間の非負整数S_1、S_2、...、S_ {2N}は、初期スコアプレーヤーの番号iを表すS_I SIスペースで区切られました。三行目は2×Nの各2つの数字は、その番号がプレイヤーIのw_i能力値であることを特徴とする請求スペースで区切られた間に正の整数は、W_2、...、W_ {2N}、W_1。
出力フォーマット
ラウンドRの終わりである整数は、Qは、プレーヤーの数をランク付けしました。
サンプル入力と出力
コピー入力#1
2 2 4
7 6 7 6
10 5 20 15ので
出力コピー#
1
分析
これは何度も並べ替え、再発注もう一度回以上という、冒頭に問題があります。。。。。。最後まで。
確かにそのシンプルなピットを感じます。。。。。案の定、途中GGを通して、いくつかのタイムアウト。
ソートソート実際にクイックソート、およびクイックソートでソート使用されています。そして、周りの安定化O(nlogn)
であれば、迅速な排水やトラバースなどを注文されたデータの各部分。。これは時間の無駄です。。
(参照ギャング問題解決)。。。。。。。
それはあなたが合併して行うことができ判明します。O(N)の時間複雑。より速く、より安定しました。
マージソート:それぞれの値(ここではいくつかのオンライングラフィックマージが得た)、新しい配列に二つの配列、小さい方(大)で比較します
二つの配列が側面比較のために、格納された値の側を注文しなければならないことを条件とマージする必要があります。
しかし主題について考えます。。私たちは、最初の最大から最小までのスコアに応じて、ゲームの前にソートされました。そして、最初のラウンドよりも。
アレイ上の勝利は、出力配列Bが配置されています。
グループA:合計スコアの降順前に基づいており、依然として下降た当選後1分;
グループB:前に、合計スコアの降順には基づいていない、何点を依然として降順。
合併を行うために、この時間を発注しているよりも後に行ってください。
そして、その上に配列し、良い循環をマージします。。。
これは、問題は解決され、注文されています。
コード
//本来一直快排的代码
#include<iostream>
using namespace std;
#include<algorithm>
int n,r,q;
struct data{
int s; //初始分
int w; //实力
int num; //编号
}d[200005];
bool cmp(data x,data y){ //按分数排序
if(x.s != y.s )
return x.s > y.s;
else
return x.num < y.num;
}
int main(){
cin>>n>>r>>q;
n = n*2;
for(int i=1;i<=n; i++){
cin>>d[i].s;
d[i].num = i;
}
for(int i=1;i<=n; i++){
cin>>d[i].w;
}
sort(d+1,d+n+1,cmp);
while(r--){
for(int i=1;i<=n;i= i+2){
if(d[i].w > d[i+1].w){
d[i].s += 1;
}else if(d[i].w < d[i+1].w){
d[i+1].s +=1;
}
}
sort(d+1,d+n+1,cmp);
}
cout<<d[q].num<<endl;
return 0;
}
//用归并的
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 200005;
struct data{
int grade;
int num;
//int w;
};
data a[maxn];
data A[100001];
data B[100001];
int w[maxn];
bool cmp(data a,data b){
if(a.grade != b.grade){
return a.grade > b.grade;
}else{
return a.num < b.num;
}
}
int n,r,q;
void mergesort(){
int i=1,j=1,k=1;
while(i<=n && j<=n){
if(A[i].grade > B[j].grade ||
(A[i].grade == B[j].grade && A[i].num < B[j].num)){
a[k].grade = A[i].grade;
a[k].num = A[i].num;
i++;
}else{
a[k].grade = B[j].grade;
a[k].num = B[j].num;
j++;
}
k++;
}
while(i<=n){
a[k].grade = A[i].grade;
a[k].num = A[i].num;
i++;
k++;
}
while(j<=n){
a[k].grade = B[j].grade;
a[k].num = B[j].num;
j++;
k++;
}
}
int main(){
cin>>n>>r>>q;
for(int i=1;i<=2*n;i++){
cin>>a[i].grade;
a[i].num = i;
}
for(int i=1;i<=2*n;i++){
cin>>w[i];
}
sort(a+1,a+1+2*n,cmp);
while(r--){
int tt =1;
for(int i=1;i<2*n;i+=2){
if(w[a[i].num] > w[a[i+1].num]){
A[tt].grade = a[i].grade+1;
A[tt].num = a[i].num;
B[tt].grade = a[i+1].grade;
B[tt].num = a[i+1].num;
}else{
A[tt].grade = a[i+1].grade+1;
A[tt].num = a[i+1].num;
B[tt].grade = a[i].grade;
B[tt].num = a[i].num;
}
tt++;
}
mergesort();
}
cout<<a[q].num<<endl;
return 0;
}