标签:归并排序
输入输出格式
输入格式:
输入文件名为swiss.in 。
输入的第一行是三个正整数N、R、Q,每两个数之间用一个空格隔开,表示有 2*N 名选手、R 轮比赛,以及我们关心的名次 Q。
第二行是2*N 个非负整数
输出格式:
输出文件名为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,
noip2011普及组第3题。
题解
先说一句,最暴力的做法即每次都快排会T。NOIP的官方数据只会给快排50分。
其实只要快排一次就可以了,然后把每一轮的胜利者和失败者分组,可以发现胜利者内部和失败者内部的相对排名是不变的,然后恍然大悟——归并排序!每一轮都模拟出结果,然后分组,直接归并即可。
Code
#include <cstdio>
#include <algorithm>
using namespace std;
struct node
{
int num, val, pw;
node(int num = 0, int val = 0, int pw = 0) :num(num), val(val), pw(pw) {}
bool operator < (const node& b) const
{
if(val > b.val) return true;
if(val < b.val) return false;
return num < b.num;
}
}T[200005], tmp[2][100005];
int n, r, q, s[200005], w[200005];
void init()
{
scanf("%d%d%d", &n, &r, &q);
for(int i = 0; i < (n << 1); ++i) scanf("%d", &s[i]);
for(int i = 0; i < (n << 1); ++i) scanf("%d", &w[i]);
for(int i = 0; i < (n << 1); ++i) T[i] = node(i + 1, s[i], w[i]);
sort(T, T + (n << 1));
}
void work()
{
while(r--)
{
for(int i = 0; i < n; ++i)
{
if(T[i << 1].pw > T[i << 1 | 1].pw)
{
++T[i << 1].val;
tmp[1][i] = T[i << 1];
tmp[0][i] = T[i << 1 | 1];
}
else
{
++T[i << 1 | 1].val;
tmp[1][i] = T[i << 1 | 1];
tmp[0][i] = T[i << 1];
}
}
int top[3] = {0, 0, 0};
while(top[0] < (n << 1))
{
if((top[1] < n) && (tmp[1][top[1]] < tmp[0][top[2]] || top[2] >= n))
{
T[top[0]++] = tmp[1][top[1]];
++top[1];
}
else
{
T[top[0]++] = tmp[0][top[2]];
++top[2];
}
}
}
printf("%d\n", T[q - 1].num);
}
int main()
{
init();
work();
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:归并排序
原文地址:http://blog.csdn.net/t14t41t/article/details/46971445