首页 > 试题广场 >

画展布置

[编程题]画展布置
  • 热度指数:1919 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
\hspace{15pt}展厅共有 N 幅画作,其艺术价值为整数 A_1,A_2,\dots ,A_N。策展人需选出其中 M 幅依次摆放。设选出后排成一列的价值为 B_1,\dots ,B_M,定义一个画展的不和谐度 L 满足

L\;=\;\sum_{i=1}^{M-1}\bigl|B_{i+1}^2-B_i^2\bigr|.

\hspace{15pt}请最小化 L 并输出其最小可能值。

输入描述:
\hspace{15pt}第一行输入两个整数 N,M\left(2\leqq M\leqq N\leqq 10^{5}\right)
\hspace{15pt}第二行输入 N 个整数 A_1\dots A_N\left(1\leqq A_i\leqq 10^{5}\right)


输出描述:
\hspace{15pt}输出一个整数,表示最小化后的 L 值。
示例1

输入

4 2
1 5 2 4

输出

3

说明

选择 \{1,2\} 得到 L=2^2-1^2=3,为最小值。
n, m = map(int, input().split())
a = list(map(int, input().split()))
a,min1 = sorted(a), float('inf')
for i in range(n-m+1):
    x,y = a[i],a[i+m-1]
    shu = y**2-x**2
    if shu < min1:
        min1 = shu
print(min1)
##此题看似很难,但是我们在做这种题的时候,都一定是转化为单循环,双循环必超时,由于不和谐度与数之间的差值和和有关,因为x平方减y平方等于x与y的和乘以x与y的差,所以xy应该尽量小,且差值也应该小,所以此时可以直接sorted,之后可以发现,因为排序后Bi的值一直在增大,所以可以去掉绝对值,所以化简成了最后一个数的平方减去第一个数的平方,由此转化成了单循环

发表于 2025-08-14 09:46:42 回复(0)
排序就不用说了,关键是这题用不到双指针。本题是固定长度 m,无需动态缩放窗口    直接枚举连续段即可。至于公式计算,因为子数组是连续有序的,在数学上可以得到累加和 = 首尾差,也就是每个大小为m的子数组的公式累加和=L = a[i + m - 1] * a[i + m - 1] - a[i] * a[i];
最后有坑点(C/C++),必须全员long long
#include <algorithm>
#include <climits>
#include <iostream>
#include <vector>
using namespace std;
int main() {
    int n, m;
    long long ans = LLONG_MAX;
    cin >> n >> m;
    vector<long long>a(n);
    for (int i=0; i<n; i++) cin>>a[i];
    sort(a.begin(), a.end());
    for (int i = 0; i <= n - m; i++) {
        long long L = a[i + m - 1] * a[i + m - 1] - a[i] * a[i];
        ans = min(ans, L);
    }
    cout << ans;
}


发表于 2025-11-12 01:10:40 回复(0)
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
//双指针就尽量往O(n)方向想,不然双循环必超时。
//好像排序之后,选任意两个点找最小的就可以了吧,因为递增序列任意两个之间肯定是最小的啊,在利用双指针找两个数就行了吧,不对因为是要找M个数,所以还是是要找一个子数组到达M个,
//注意优化的点,b增加后,a指针移动后,只需要减去剔除的元素差,加上新进来的元素差就可以了,这样时间复杂度就是On了,避免重复计算

int compare(const void*p1,const void *p2)
{
    return *(int*)p1-*(int*)p2;
}
int main() {
    int N,M;
    scanf("%d %d",&N,&M);
    int array[N];
    for(int i=0;i<N;i++)
    {
        scanf("%d",&array[i]);
    }

    //排序一下
    qsort(array, N, sizeof(int), compare);
    long long min_L;   //记录最小L,结果可能会很大,所以必须用longlong
    int a=0,b=0+M-1; //设定一个窗口
    //先统计第一个窗口的值
    long long temp_L=0;
    for (int i=a;i<=b-1&&b<=N-1; i++) {
        temp_L += (long long)array[i+1] * array[i+1] - (long long)array[i] * array[i];
    }
    min_L=temp_L;
    //统计剩余窗口
    a++;
    b++;
    while (b<=N-1) {
       // long temp_L=0;
            //对哦,我怎么就没想到呢,只需要减去剔除的元素差,加上新进来的元素差就可以了,这样时间复杂度就是On了,避免重复计算

        temp_L -= (long long)array[a] * array[a] - (long long)array[a-1] * array[a-1];
        temp_L += (long long)array[b] * array[b] - (long long)array[b-1] * array[b-1];
        
        if (temp_L<min_L) {
            min_L=temp_L;//统计最小
        }
        a++;//滑动到下一个窗口
        b++;
    }
    
    printf("%lld",min_L);
    return 0;
}

发表于 2025-10-19 19:16:29 回复(1)
import java.util.*;
import java.io.*;


// 定长滑动窗口统计满足条件的最小区间值
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        String[] line1 = bf.readLine().split(" ");
        int n = Integer.parseInt(line1[0]);
        int m = Integer.parseInt(line1[1]);
        int[] str = Arrays.stream(bf.readLine().split(" ")).mapToInt(
                        Integer::parseInt).toArray();
        Arrays.sort(str);

        long minL = 0; //注意精度问题,L超过21亿的范围
        //第一个窗口的minL
        for (int i = 1; i < m; i++) {
            minL += Math.pow(str[i], 2) - Math.pow(str[i - 1], 2);
        }
        //定长窗口的L
        long conL = minL;
        for (int r = m; r < n; r++) {
            //注意精度损失,int*int结果仍为int,会有损失。pow内隐式转换int为double不会损失。
            //新增元素r的L大小控制变化
            conL += Math.pow(str[r], 2) - Math.pow(str[r - 1], 2);
            //减少元素r-m的L大小控制变化
            conL -= Math.pow(str[r - m + 1], 2) - Math.pow(str[r - m], 2);

            if (conL < minL) {
                minL = conL;
            }
        }
        System.out.println(minL);

    }
}

发表于 2025-08-31 12:08:25 回复(1)