首页 > 试题广场 >

锦标赛

[编程题]锦标赛
  • 热度指数:626 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 63M,其他语言126M
  • 算法知识视频讲解
组委会正在为美团点评CodeM大赛的决赛设计新赛制。

比赛有 n 个人参加(其中 n 为2的幂),每个参赛者根据资格赛和预赛、复赛的成绩,会有不同的积分。比赛采取锦标赛赛制,分轮次进行,设某一轮有 m 个人参加,那么参赛者会被分为 m/2 组,每组恰好 2 人,m/2 组的人分别厮杀。我们假定积分高的人肯定获胜,若积分一样,则随机产生获胜者。获胜者获得参加下一轮的资格,输的人被淘汰。重复这个过程,直至决出冠军。

现在请问,参赛者小美最多可以活到第几轮(初始为第0轮)?

输入描述:
第一行一个整数 n (1≤n≤ 2^20),表示参加比赛的总人数。
接下来 n 个数字(数字范围:-1000000…1000000),表示每个参赛者的积分。
小美是第一个参赛者。


输出描述:
小美最多参赛的轮次。
示例1

输入

4
4 1 2 3

输出

2
#通过率百分之95,超过使用内存,可能是排序的问题
#!/usr/bin/env python
# coding=utf-8


if __name__ == "__main__":
    m=int(raw_input())
    a=map(int,raw_input().split())
    n=a[0]
    a.sort()
    roun=0
    for k in range(1,21):
        if 2**k==m:
            h=k
    if len(a)==1:
        roun=0
    elif n<a[1]:
        roun= 0
    elif n>=a[-1]:
        roun= h
    else:
        for i in range(h) :
            x=(a[:2**i])[-1]
            y=(a[:2**(i+1)])[-1]
            if x<=n<y:
                roun= i
    print roun


编辑于 2018-04-19 15:13:45 回复(0)
#比赛只在分数小于等于小美的这群人里进行,比小美分数高的不管
#所以统计算上小美在内的分数小于等于小美的人数
#每次除以2,取整数部分(多出来的那一个和分数高的人去比了)
#最后,能除几次2,就能比几次。
#注意的情况是,如果小美不是全场最大,最后一次厮杀小美输掉
#这局不算“活下来”,所以最后一次不算。  #include <iostream>
#include <vector>
using namespace std;
int main() {
	long long n;
	while (cin >> n) {
		long long d1,d2;
		if (n == 1)
		{
			cin >> d1;
			cout << 0 << endl;
			continue;
		}
		if (n == 2)
		{
			cin >> d1;
			cin >> d2;
			if (d1 < d2)
				cout << 0 << endl;
			else
				cout << 1 << endl;
			continue;
		}
		long long tmp, count = 1, myScore, answer = 0;
		cin >> myScore;
		for (size_t i = 0; i < n - 1; i++)
		{
			cin >> tmp;
			if (tmp <= myScore)	count++;
		}
		while (count != 1)
		{
			count /= 2;
			answer++;
		}
		cout << answer << endl;
	}
}

编辑于 2017-06-19 20:00:18 回复(0)
数学方法,看小美的分数在升序序列中排在第几(相等的排到前面去)。因为每次淘汰一半的人,对这个排名求log2就是她最多能挨过的轮数。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        String[] scores = br.readLine().split(" ");
        int mei = Integer.parseInt(scores[0]);
        int rank = 1;
        // 找到有多少人可以排小美前面
        for(int i = 1; i < n; i++){
            if(Integer.parseInt(scores[i]) <= mei){
                rank++;
            }
        }
        System.out.println(log2(rank));
    }
    
    private static int log2(int n) {
        return (int)(Math.log(n) / Math.log(2));
    }
}
注意求小美分数的排名千万不要去排序,这个数据量下排序会超时,直接O(N)的复杂度看有多少人可以排在她的前面就行。
编辑于 2022-01-10 21:11:19 回复(0)
import java.util.Scanner;


public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		int my = scanner.nextInt();
		
		int small = 1;
		for (int i = 1; i < n; i++) {
			
			if (scanner.nextInt()<=my) {
				small++;
			}
		}
		
		System.out.println((int)Math.floor(Math.log(small)/Math.log(2)));
		scanner.close();
		
	}

}
道理我都懂,以2为底k(小美的能力在所有人当中第k小)的对数,再向下取整,但是为什么老是提示内存超限呢?只过了85%的数据

发表于 2017-06-18 01:40:46 回复(6)
int fun(int n,vector<int> vec)
{
    if(vec.size() == 0)
        return 0;
    if(vec.size() == 1)
        return 0;
    if(vec.size() == 2)
        return 1;

    int value = vec[0];
    sort(vec.begin(),vec.end());

    int maxRound = 1;
    int num = 2;
    for(int i = 1; i < 21; i++)
    {
        num *=2;
        if(num >= n)
        {
            maxRound = i+1;
            break;
        }
    }
    int maxSize = vec.size();
    int max = 2;
    int min = 1;
    for(int i = 1; i < maxRound; i++)
    {
        max = (max >= maxSize ? maxSize-1 : max);
        if(value >= vec[min] && value < vec[max])
        {
            return i-1;

        }
        min *= 2;
        max *= 2;
    }
    max = max >= maxSize ? maxSize : max;
    if(value >= vec[max])
        return maxRound-1;
    return 0;

}

int main(int argc ,char* argv[])
{
    int n;
    cin >> n ;

    vector<int> vec;
    for(int i = 0; i < n; i++)
    {
        int val;
        cin >> val;
        vec.push_back(val);
    }


    cout << fun(n,vec) << endl;

    return 0;
}

编辑于 2020-09-11 09:50:57 回复(1)
#include <bits/stdc++.h>
using namespace std;
/*
bool cmp(pair<int,double> a,pair<int,double> b)
{
    return a.second>b.second;
}
*/
int main()
{
    int n;
    cin>>n;
    int mei;
    cin>>mei;
    int count = 1;
    for(int i = 1;i<n;i++)
    {
        int temp;
        cin>>temp;
        if(temp<=mei) count++;
    }
    int result = 0;
    while(count>>1)
    {
        count>>=1;
        result++;
    }
    cout<<result<<endl;
    return 0;
}

发表于 2018-06-09 23:59:25 回复(0)
比小美分数高的永远比她高,比小美分数低的永远比她低
1. 输入数组;
2. 统计有多少人分数低于或等于小美(包括小美);
3. 不断地将步骤二的结果除以2并向下取整,直到为0,循环的次数就是轮数
#include <iostream>
using namespace std;

int main()
{

//intput scores
int len(0);
cin >> len;
int *score = new int[len];
for (int i = 0; i < len; ++i) { cin >> score[i]; }

//count how many people get lower scores?(include equal)
int numLowerScores(0);
for (int i(0); i < len; ++i)
{
if (score[i] <= score[0]) { ++numLowerScores; }
}

int maxTimes(0);
while (int(numLowerScores /= 2)) { ++maxTimes; }

cout << maxTimes;

return 0;
}

编辑于 2018-03-21 22:12:57 回复(0)
//只通过了95%的数据
//不懂为什么会有样例是1048576,输出17,奇怪

import java.util.Scanner;

public class Main{

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int [] score = new int [n];
        for(int i = 0;i < n;i++){
            score[i] = scanner.nextInt();
        }
        
        int max = score[0];
        int count = 0;
        int number = 0;
        int xiaomei = score[0];
        for(int i = 1;i < n;i++){
            if(score[i] <= xiaomei){
                number++;
            }
            if(score[i] > max){
                max = score[i];
            }
        }
        if(number == 0){
            System.out.println(0);
            return;
        }
        else {
            while(true){
                if(number/2 > 0){
                    count++;
                    number /= 2;
                }
                else {
                    break;
                }
            }
            /*if(xiaomei == max){
                System.out.println(count);
            }
            else {
                System.out.println(count-1);
            }*/
            System.out.println(count);
        }
        

    }

}

发表于 2017-12-26 20:21:28 回复(1)
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
int main(){
	int n;
	while(cin>>n){
		vector<int> score(n,0);
		for(int i=0;i<n;i++)
			cin>>score[i];
		int m=score[0],index=1,turns;
		for(int i=0;i<n;i++){
			for(int j=n-1;j>i;j--){
				if(score[j]<score[j-1]){
				int temp=score[j-1];
				score[j-1]=score[j];
				score[j]=temp;
				}
			}
		}
		for(int i=0;i<n;i++)
			if(m==score[i])
				index=i+1;

		turns=(int)(log(index*1.0)/log(2.0));
		cout<<turns<<endl;
	}
	//system("pause");
	return 0;
} 2为底k(小美的能力在所有人当中第k小)的对数,再向下取整 运行超时:您的程序未能在规定时间内运行结束,请检查是否循环有错或算法复杂度过大。
case通过率为70.00%
发表于 2017-07-03 20:12:47 回复(0)
import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Scanner scan = new Scanner(System.in);
		while(scan.hasNext()){
			int n = scan.nextInt();
			int p = scan.nextInt();
			int count = 0;
                        int t = 0;
			for(int i = 0; i < n - 1; i++){
				t = scan.nextInt();
				if(t <= p)
					count++;				
			}
			
			System.out.println(getMax(count,n));
		}
	}

	private static int getMax(int count, int n) {
		// TODO Auto-generated method stub
		
		if(count == 0)
			return 0;
		
		if(index == n - 1)
			return (int) (Math.log(n)/Math.log(2));
		
		if(index >= (n/2 - 1))
			return (int) (Math.log(n/2)/Math.log(2));
		else
			return (int) (Math.log(count + 1)/Math.log(2));
		
	}
}

通过率只有85%,提醒超出内存限制,不懂。求解

发表于 2017-06-24 11:30:59 回复(0)
import java.util.Scanner;

public class Main {
	
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int n = scan.nextInt();
		int a[] = new int[n];
		a[0] = scan.nextInt();
		int xm = a[0];
		int left = -1, right = 0;
		for (int i = 1; i < n; i++) {
			a[i] = scan.nextInt();
			if (a[i] <= xm)
				left++;
			else
				right++;
		}
		int count = 0;
		while (left != -1) {
			if (left % 2 == 1) {
				right = (right + 1) / 2;
				left = (left - 1) / 2 - 1;
			} else {
				right = right / 2;
				left = left / 2 - 1;
			}
			count++;
		}
		System.out.println(count);
		scan.close();
	}

}
先统计比小美积分小(包括相等)的参赛者数,以及比小美积分高的参赛者数。
优先消去积分高的参赛者,所以最好让高积分的自己先两两消除,消除掉一半,再看积分低的,如此循环
发表于 2017-06-19 15:59:49 回复(0)
为什么我觉得样例那组数据可以打3场
因为题目上说每轮有m个人参见分为m/2组,显然m是偶数,然而没有说m是当前的全部人数呀,感觉可以一批在打一批看戏,那么样例数据里,小美计分4可以力刚3轮才对呀?
咋回事?题目描述有问题?
发表于 2017-06-19 07:13:06 回复(1)
//想法是都排个序,然后每次都与当前积分最少的选手比赛

import java.util.Arrays;
import java.util.Scanner;

public class Main {

    final static int MAX_N = (int) Math.pow(2,20);
    public static void main(String[] args) {
        int[] a = new int[MAX_N];
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        for(int i = 0 ; i < n ;i++){
            a[i] = sc.nextInt();
        }
        
        int count = 0;
        if(n==1){
            count = 0;
        }else{
            int xiaoMeiScore = a[0];
            int[] other = new int[n-1];
            System.arraycopy(a, 1, other, 0, n-1);
            Arrays.sort(other);
            if(xiaoMeiScore >= other[other.length - 1]) count = (int)(Math.log((double)(n))/Math.log((double)2));
            else
                count = taotai(xiaoMeiScore,other,0);
        }
        System.out.println(count);
        
    }
    
    public static int taotai(int first , int[] other , int n){
        if(first < other[0]){
            return n;
        }
        int[] other2 = new int[other.length -1];
        System.arraycopy(other, 1, other2, 0, other.length -1);
        int[] next = new int[other2.length / 2];
        for(int i = 0 ; i < next.length ; i++){
            next[i] = other2[i * 2 + 1];
        }
        
        return taotai( first , next , n + 1);

    }

}
发表于 2017-06-18 21:16:40 回复(0)