闭门造车【NOIP2016提高A组模拟9.10】

题目

自从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)=(ij)2+(sumisumj)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);
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值