目录
题目:
题目描述:
题目链接:
思路:
核心思路:
排序+滑动窗口
思路详解:
由题意可以理解为:排列时,相邻的两幅画的艺术价值平方的差值越小越好
先理解为什么要排序?排序后的协调性一定优于输入时乱序的协调性
简单证明一下:假设选三幅画,画的艺术价值按排列顺序是x y z,实际x<z<y,则按照题意求L=|y*y-x*x|+|z*z-y*y|=(y*y-x*x)+(y*y-z*z)。但是如果按照艺术价值排序的话是x z y,再按照题意求L=|z*z-x*x|+|y*y-z*z|=y*y-x*x,显然对比上面少了y*y-z*z这部分,因为y>z所以这部分也肯定大于0,即按照艺术价值排序后再排列的L小于乱序排列的L
当然这只是我不严谨的证明,如果想要严谨的证明大家可以去洛谷看其他大佬题解的数学证明
数组a排序后比较每个连续区间长度为m的L即可,取最小的L就是正确答案了。在这个过程中,我们还可以优化L的计算,先把输入的a[i]对自己平方再存入a[i]再排序,假设此时是a[3] a[4] a[5] a[6],则L=|a[4]-a[3]|+|a[5]-a[4]|+|a[6]-a[5]|,因为我们已经排序过了,所以绝对值可以直接去掉,则L=a[6]-a[3],所以求一段区间[l,r]的L可以简化为a[r]-a[l]
再来聊聊滑动窗口,其实就是双指针算法的一种,大家也可以自行去搜比较热门的博客去学习。在这题里,就是先初始化左右边界left=1,right=m,把索引闭区间[left,right]称为一个窗口。由题意这个窗口的大小就是m是固定的,只需要把整个窗口一直向右滑动,直到right到达a数组的最后一位。在这个滑动窗口的过程中求a[r]-a[l]的最小值就是正确答案了
代码:
代码详解:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10; //多开一点,防止数组越界
int n,m;
ll res=1e18; //先初始化res为很大的值,在窗口滑动过程中取最小值
ll a[N]; //由题输入的a[i]最大为1e5,则a[i]*a[i]最大为1e10会爆int,要开long long
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i]*=a[i]; //将每次输入的数对自己平方再存入a[i]
}
sort(a+1,a+1+n); //因为i从1开始,所以传入sort的首地址是a+1,有n个元素要排序
for(int l=1,r=m;r<=n;l++,r++) //初始化l=1,r=m,窗口大小不变只需要向右滑动,即l++,r++
{ //滑到终点的判断就是r==n
res=min(res,a[r]-a[l]); //每次求a[r]-a[l]并取最小值
}
cout<<res<<endl;
return 0;
}