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

来源:互联网 发布:gzip linux 编辑:程序博客网 时间:2024/05/14 10:32

题目

自从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 longusing 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);}

这里写图片描述

0 0
原创粉丝点击