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

⭐ 快读快写
⭐ 注意学生本人的分数变化对 刷题量比他大或小的 人数的影响
⭐ 分类讨论
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();
}
}

浙公网安备 33010602011771号