最少刷题数 蓝桥真题 模拟 分类讨论 前缀和 双指针

原题地址
在这里插入图片描述

⭐ 快读快写
⭐ 注意学生本人的分数变化对 刷题量比他大或小的 人数的影响

⭐ 分类讨论

import java.io.*;
import java.util.*;

public class Main
{
	static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));

	public static void main(String[] args) throws IOException
	{

//        Scanner scanner = new Scanner(System.in);
//        int n = scanner.nextInt();
		int n = Integer.parseInt(in.readLine());
		int[] a = new int[n];// 每个学生的分数数组
		int[] b = new int[n];// 备份数组
		String[] ss = in.readLine().split(" ");

		for (int i = 0; i < n; i++)
		{
			a[i] = Integer.parseInt(ss[i]);
			b[i] = a[i];
		}
		Arrays.sort(b);// 默认按升序排序
		int mid = b[n / 2];// mid 表示中位数
		int low = 0;// 记录比中位数小的数的个数
		int big = 0;// 记录 大
		for (int i = 0; i < n; i++)
		{
			if (a[i] < mid)
				low++;
			if (a[i] > mid)
				big++;
		}
		// 记录刷题量为中位数时是否符合题目要求(即 big <= low),0 表示符合要求,1表示不符合要求
		int flag = 0;
		if (big > low)
			flag = 1;

//		枚举 每一位 学生
		for (int i = 0; i < n; i++)
		{
			if (a[i] > mid)
			{
				out.write(0 + " ");
			} else if (a[i] == mid)
				out.write(flag + " ");
			else
			{
// 				学生本身的刷题数就小于 mid,自己以前的记录应该失效,所以至少要刷多一道
//				而mid道的同学至少有一个,所以刷到 mid + 1即可
				if (big >= low)// 刷到 mid 也不满足 big <= low,得刷多一道
					out.write((mid - a[i] + 1) + " ");
				else
				{// 此分支 low >= big ,刷到 mid 道 即可
					out.write((mid - a[i]) + " ");
				}
			}
		}
		out.flush();
	}
}

⭐ 前缀和+双指针 (过 80%)

package algorithm.lanQiao.二分;

import java.util.*;
import java.io.*;

public class 最少刷题数
{
	static int N = 100010;
	static int[] a = new int[N];// 分数数组,记录第 i 个同学的分数
	static int[] b = new int[N];// 记录 分数 i 出现的次数
	static int[] s = new int[N];// 前缀和数组

	static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));

	public static void main(String[] args) throws IOException
	{
		Scanner sc = new Scanner(System.in);
//		int n = sc.nextInt();
		int n = Integer.parseInt(in.readLine());
//		输入数据
		String[] ss = in.readLine().split(" ");
		for (int i = 1; i <= n; i++)
		{
//			int t = sc.nextInt();
			int t = Integer.parseInt(ss[i - 1]);
			a[i] = t;
			b[t]++;
		}
//		预处理前缀和数组
		for (int i = 1; i <= n; i++)
		{
			s[i] = s[i - 1] + b[i];
		}

//		求解
		for (int i = 1; i <= n; i++)
		{
//			只要后边比它 大 的 <= 前边比它小的,直接输出
			if (s[100000] - s[a[i]] <= s[Math.max(0, a[i] - 1)])
			{
//				System.out.print(0 + " ");
				out.write(0 + " ");
			} else if (s[100000] - s[a[i]] > s[Math.max(0, a[i] - 1)])
			{
//				二分查找需要刷多少题才能符合条件
				int l = a[i] + 1;
				int r = 100000;
				while (l < r)
				{
					int mid = l + r >> 1;
//												细节-1 ,减去本身(l > a[i],a[i] 也占了一个位置)
					if (s[100000] - s[mid] <= s[mid - 1] - 1)
						r = mid;
					else
					{
						l = mid + 1;
					}
				}

//				System.out.print((r - a[i]) + " ");
				out.write(r - a[i] + " ");
			}
		}
		out.flush();

	}
}

posted @ 2023-04-05 15:21  兑生  阅读(19)  评论(0)    收藏  举报  来源
Live2D