题目
自从htn体验了一把飙车的快感,他就下定决心要闭门造车!但是他两手空空怎么造得出车来呢?无奈的他只好来到了汽车零部件商店。
一走进商店,玲琅满目的各式零件看得htn眼花缭乱。但是他很快便反应过来:我只要买一套好的零件就行。首先它们的性能差不能太大,否则汽车的兼容性不好,开着开着就损坏了;其次,当然是越便宜越好了!为了打造一辆顶级跑车,htn陷入了沉思……
现在商店中有 N 件零件,给出这 N 件零件的价格,其性能等于价格。htn要从中购买一套零件,即选取这个序列的一个子串(连续一段)。要求如下:
1、这一套零件个数要大于等于2(这才算一套)。
2、这套零件的性能差为首尾两个零件的性能差(htn觉得每一个都比较性能差实在是太累了)。
3、购买这套零件的价格和为它们各自价格的总和。
4、最终的总花费为 性能差²+价格和²。
5、由于商店最近有优惠活动,所以每一套零件的第一个都是免费的。对此毫无经验的htn只好向经验丰富的你求助了。
样例输入:
第一行一个正整数 N ,表示零件个数。
第二行 N 个正整数, ai 表示第 i 个零件的价格(即性能)
5
6 10 9 8 3
样例输出:
一个正整数,表示最小花费。
34
数据范围:
对于 30% 的数据, N≤1000。
对于 50% 的数据, N≤10000。
对于 100% 的数据, N≤100000。
剖解题目
给一个序列,要求取出连续的一段长度大于等于2的序列,使代价最小。
思路
暴力很明显,想想优化吧。
然而这题却是一个二维点对问题。。。。
解法
30%:暴力,时间:
O(n2)
50%:不会QwQ。
100%:两种解法
解法一:转化为二维点对问题,然后分治求出最近点对。
式子:
Dis(i,j)=(i−j)2+(sumi−sumj)2
. 时间
O(nlogn)
然而我还没说过什么二维点对…….QAQ。
解法二:可以证明出若以一个点为头,向后连续取4个及以上,答案不会优于取1~3个。时间
O(3n)
代码(解法二)
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
using namespace std;
const int maxn=1e5+5;
int a[maxn],sum[maxn];
int ans,n;
ll sqr(ll x)
{
return x*x;
}
int main()
{
//freopen("T.in","r",stdin);
scanf("%d",&n);
fo(i,1,n) {
scanf("%lld",&a[i]);
sum[i]=sum[i-1]+a[i];
}
ans=1e8;
fo(i,1,n-1){
fo(j,i+1,i+4){
if(j>n) break;
ll tot=sqr(sum[j]-sum[i-1]-a[i])+sqr(a[i]-a[j]);
if (tot<ans) ans=tot;
}
}
printf("%lld",ans);
}