歌名 - 歌手
0:00

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

    题目

    自从htn体验了一把飙车的快感,他就下定决心要闭门造车!但是他两手空空怎么造得出车来呢?无奈的他只好来到了汽车零部件商店。
    一走进商店,玲琅满目的各式零件看得htn眼花缭乱。但是他很快便反应过来:我只要买一套好的零件就行。首先它们的性能差不能太大,否则汽车的兼容性不好,开着开着就损坏了;其次,当然是越便宜越好了!为了打造一辆顶级跑车,htn陷入了沉思……
    现在商店中有 N 件零件,给出这 N 件零件的价格,其性能等于价格。htn要从中购买一套零件,即选取这个序列的一个子串(连续一段)。要求如下:
    1、这一套零件个数要大于等于2(这才算一套)。
    2、这套零件的性能差为首尾两个零件的性能差(htn觉得每一个都比较性能差实在是太累了)。
    3、购买这套零件的价格和为它们各自价格的总和。
    4、最终的总花费为 性能差²+价格和²。
    5、由于商店最近有优惠活动,所以每一套零件的第一个都是免费的。对此毫无经验的htn只好向经验丰富的你求助了。

    分析

    不得不说,题面不错。
    讲个水法,这里运用到著名的ljj水法,将\(O(n^2)\)暴力的第二层枚举修改一下,只枚举500个。
    水法万岁(≧▽≦)/

    正解:
    首先把问题转化为下面这个式子:
    \(Dis(i,j)=(a[i]-a[j])^2+(sum[i]-sum[j])^2\)
    答案就是最近点对

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    const long long maxlongint=2147483647;
    const int mo=1000000007;
    const int N=100005;
    using namespace std;
    long long a[N],n,ans=maxlongint,sum[N];
    int main()
    {
    	scanf("%lld",&n);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%lld",&a[i]);
    		sum[i]=sum[i-1]+a[i];
    	}
    	for(int i=1;i<=n-1;i++)
    		for(int j=i+1;j<=((n>i+500)?i+500:n);j++)
    		{
    			if((sum[j]-sum[i])*(sum[j]-sum[i])+(a[i]-a[j])*(a[i]-a[j])<ans)
    			{
    				ans=(sum[j]-sum[i])*(sum[j]-sum[i])+(a[i]-a[j])*(a[i]-a[j]);
    			}
    		}
    	printf("%lld",ans);
    }
    
    
    posted @ 2018-05-16 21:00  无尽的蓝黄  阅读(109)  评论(0编辑  收藏  举报