蓝桥杯国赛分考场

Posted ~千里之行,始于足下~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯国赛分考场相关的知识,希望对你有一定的参考价值。

试题 J: 分考场
【问题背景】

古语有云:春风得意马蹄疾,一日看尽长安花。
当然在一场考试中所有人都春风得意马蹄疾是不可能的,尤其是碰到一些毒瘤出题人的时候。

【问题描述】

又到了每月一次的月考,又是 xf 老师出题。

上一次 xf 老师出的题太毒瘤了,平均分只有 40 多,同学们都非常不满意,毕竟别的科的平均分都是 80 多。

这次 xf 为了不被同学们寄刀片,想了一个办法:只公布所有考场的平均分的平均分。这样他就可以通过调整考场的分配方式,使得平均分显得高。(每个考场都可以容纳无限人)

每次考试也不是所有同学都参加的,只有学号在 [l,r] 这个区间中的同学会参加。

他想知道对于每次考试,他调整过考场后,所有考场的平均分的平均分的最大值。

当然,同学们也可能会努力学习或整日颓废使成绩发生改变。

【输入格式】

输入的第一行包含一个整数 n。

第二行包含 n 个整数,第 i 个数 vi,表示开始时每个同学的成绩。

第三行包含一个整数 q,表示有 q 次操作。

之后 q 行,每行描述一个操作,第一个数表示操作类型。

如果操作为 1 p x,表示学号为 p 的同学分数变为 x。

如果操作为 2 l r k, 表示把学号在 [l,r] 中的同学分成 k 个考场,求这 k 个考场的平均分的平均分的最大值

【输出格式】

对于每个 2 操作输出一行,四舍五入保留正好 3 位小数。

【样例输入】

5
5 3 4 2 1
5
2 1 4 3
1 4 8
2 3 5 3
1 2 2
2 1 3 2

【样例输出】

3.833
4.333
4.000
【样例说明】

第一个操作询问学号在 [1, 4] 之间的同学分成 3 个考场的平均分的平均分的最大值,最优策略是:{1}, {2, 4}, {3},平均分是

第二个操作把学号为 4 的同学的分数变为 8。

第三个操作询问学号在 [3, 5] 之间的同学分成 3 个考场的平均分的平均分的最大值,最优策略是:{3}, {4}, {5}。

第四个操作把学号为 2 的同学分数变为 2。

第五个操作询问学号在 [1, 3] 之间的同学分成 2 个考场的平均分的平均分的最大值,最优策略是:{1}, {2 3}。

【评测用例规模与约定】

对于全部评测用列,n ≤ 200000, q ≤ 200000, 任意时刻同学的分数 vi ≤ 10^9,k ≤ r − l + 1。

评测时将使用 10 个评测用例测试你的程序,每个评测用例的限制如下:
在这里插入图片描述
分析
把 l 到 r 之间分为 k 个考场,求平均分的平均分最大值,即把 l 到 r 之间的数据排序(逆序),大的一个人为一个考场,剩下最后一个考场就所有人在里边。上例子:
比如【5 4 3 2 1】3 个考场,【5】为一个考场,【4】为一个考场,【3 2 1】 为最后一个考场,这样才能保证平均分的平均分最大(每一个考场的平均分相加除以考场个数)。
以上n的规模,v的规模特别大,使用一般的排序会超时,而且题中分数均为大整数,所以使用基数排序更优。

c++代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int n;
int q;

int numOfDigits(int num)
{
	int count = 0;
	while (num)
	{
		num /= 10;
		count++;
	}
	return count;
}
//基数排序 
void radixSort(int arr[], int len)
{
	//int len = sizeof(arr) / sizeof(arr[0]);
	int maxValue = INT_MIN;//求数组中最大值 
	for (int i = 0; i < len; i++)
	{
		if (arr[i] > maxValue)
		maxValue = arr[i];
	}
	int max_wei = numOfDigits(maxValue);//返回最大值的数位个数 
	int now_wei = 1;
	int n = 1;
	int bucket[10][len] = {0};
	int count[10] = {0};//十个桶分别计数 
	while (now_wei <= max_wei)//循环最大值的数位趟 
	{
		for (int i = 0; i < len; i++)
		{
			int d = ((arr[i]/n)%10);
			bucket[d][count[d]++] = arr[i];
		}
		int k = 0;
		for (int i = 0; i <= 9; i++)
		{
			if (count[i] != 0)
			{
				for (int j = 0; j < count[i]; j++)
			    {
			    	arr[k++] = bucket[i][j];
				}
			}
			count[i] = 0; 
		}
		n *= 10;
		now_wei++;
	} 
}
void fengkaochang(int v[], int l, int r, int k)
{
	int count = 0;
	int len = r - l + 1;//计算长度 
	int arr[len] = {0};
	for (int i = l; i <= r; i++)
	{
		arr[count++] = v[i];
	}
	//sort(arr, arr+len);
	radixSort(arr, len);//基数排序 
//	for (int i = 0; i < len; i++)
//	cout << arr[i] << " ";
//	cout << endl;
	double sum = 0.0, avg = 0.0;
	for (int i = 0; i <= len - k; i++)
	{
		sum += arr[i];
	}
	//cout << sum << endl;
	avg = sum / (len-k+1);
	//cout << avg << endl;
	for (int i = len-k+1; i < len; i++)
	{
		avg += arr[i];
	}
	avg = avg / k;
	//cout << avg << endl;
	printf("%.3f\\n", avg);
}
int main()
{
	cin >> n;
	int v[n+1] = {0};//分数下表从1开始 
	for (int i = 1; i <= n; i++)
	cin >> v[i];
	cin >> q;
	int op[q][4] = {0};
	for (int i = 0; i < q; i++)
	{
		cin >> op[i][0];
		if (op[i][0] == 1)
		{
			cin >> op[i][1] >> op[i][2];
		}
		else
		{
			cin >> op[i][1] >> op[i][2] >> op[i][3];
		}
	}
	for (int i = 0; i < q; i++)
	{
		if (op[i][0] == 1)
		{
			v[op[i][1]] = op[i][2];
		}
		else
		{
			int l = op[i][1];
			int r = op[i][2];
			int k = op[i][3];
			fengkaochang(v, l, r, k);
		}
	}
	
	//测试
	/*cout << n << endl;
	for (int i = 1; i <= n; i++)
	cout << v[i] << " ";
	cout << endl;
	cout << q << endl;
	for (int i = 0; i < q; i++)
	{
		if (op[i][0] == 1)
		cout << op[i][0] << " " << op[i][1] << " " << op[i][2] << endl;
		else
		cout << op[i][0] << " " << op[i][1] << " " << op[i][2] << " " << op[i][3] << endl;
	 } */
	
	return 0;
 } 

java代码:

import java.util.Arrays;
import java.util.Scanner;
public class Test {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] v = new int[n+1];
        for(int i = 1; i < v.length; i++)
            v[i] = in.nextInt();
        int q = in.nextInt();
        int[][] op = new int[q][4];
        for(int i = 0; i <= q-1; i++){
            op[i][0] = in.nextInt();
            if(op[i][0] == 1)
                for(int j = 1; j <= 2; j++)
                    op[i][j] = in.nextInt();
            else
                for(int j = 1; j <= 3; j++)
                    op[i][j] = in.nextInt();
        }
        for(int i = 0; i <= q-1; i++){
            if(op[i][0] == 1)
                v[op[i][1]] = op[i][2];
            else{
                int l = op[i][1];
                int r = op[i][2];
                int[] vc = new int[r-l+1];
                System.arraycopy(v, l, vc, 0, r-l+1);
                fenkaochang(vc, op[i][3]);
            }
        }
    }
    public static void fenkaochang(int[] vc, int k){
        java.text.DecimalFormat df = new java.text.DecimalFormat("#.000");
        //Arrays.sort(vc);
        radixSort(vc);
        double sum = 0, avesum = 0;
        for (int i = 0; i <= vc.length-k; i++)
        sum += vc[i];

        avesum = sum / (vc.length - k + 1);
        for(int i = vc.length - k + 1; i < vc.length; i++)
            avesum += vc[i];
        avesum /= k;
        System.out.println(df.format(avesum));
    }
    public static void radixSort(int[] arr){
        int max_wei = 9, now_wei = 0, n = 1;
        int[][] bucket = new int[10][arr.length];
        int[] count = new int[10];
        while (now_wei <= max_wei){
            for (int i = 0; i < arr.length; i++){
                int d = ((arr[i] / n) % 10);
                bucket[d][count[d]] = arr[i];
                count[d]++;
            }
            int k = 0;
            for(int i = 0; i <= 9; i++) {
                if(count[i] != 0)
                    for(int j = 0; j < count[i]; j++)
                    { arr[k] = bucket[i][j];   k++; }
                count[i] = 0;
            }
            n *= 10;
            now_wei++;
        }
    }
}

详细的排序请访问这位大佬
本题的思路来自辅导老师,学到了很多东西,感谢老师!
欢迎大佬指正!

以上是关于蓝桥杯国赛分考场的主要内容,如果未能解决你的问题,请参考以下文章

蓝桥杯国赛真题08python约分 蓝桥杯青少年组python编程 蓝桥杯国赛真题解析

蓝桥杯国赛真题08python约分 蓝桥杯青少年组python编程 蓝桥杯国赛真题解析

蓝桥杯国赛真题05python读数系统 蓝桥杯青少年组python编程 蓝桥杯国赛真题解析

蓝桥杯国赛真题04python输出平方 蓝桥杯青少年组python编程 蓝桥杯国赛真题解析

蓝桥杯国赛真题19Scratch青蛙王子 青少年组 scratch蓝桥杯国赛真题和答案讲解

蓝桥杯国赛真题06python绘制菱形圆环 蓝桥杯青少年组python编程 蓝桥杯国赛真题解析