列表

详情


NC17068. 序列回归

描述

    评评有一个数列{a1,a2,...,an}。她想求一个数列{b1,b2,...,bn},使得b- bi-1 ≤ bi+1 - bi 对所有 2 ≤ i < n都成立,并且
               
尽量小。B数列中的元素可以是实数。请求出这个最小值。

输入描述

第一行一个正整数n(1≤n≤1,000,000)。
接下来一行n个整数依次表示{a1,a2,...,an}(-106 ≤ai≤106)。

输出描述

仅一行,表示答案。如果答案是整数x,输出这个整数x。否则答案是分数p/q,其中p和q的最大公约数为1,输出“p/q”(不含引号)。

示例1

输入:

3
1 2 3

输出:

0

示例2

输入:

3
1 2 2

输出:

1/4

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 132ms, 内存消耗: 8308K, 提交时间: 2020-08-27 11:41:36

#include<bits/stdc++.h>
#define ll long long
using namespace std;

ll a[1001000],s[1001000];

int main()
{
    ll n;
    scanf("%lld",&n);
    ll top=0;
    for(ll i=0;i<n;i++) scanf("%lld",&a[i]);
    for(ll i=0;i<n;i++){
        while(top>1&&(a[i]-a[s[top]])*(s[top]-s[top-1])<=(a[s[top]]-a[s[top-1]])*(i-s[top]))  top--;
        s[++top]=i;
    }
    ll x=0,y=1;
    for(ll i=1;i<=top;i++){
        for(ll j=s[i];j<=s[i+1];j++){
            ll xx=(a[j]-a[s[i]])*(s[i+1]-s[i])-(a[s[i+1]]-a[s[i]])*(j-s[i]);
            if(xx<0) xx=-x;
            ll yy=s[i+1]-s[i];
            if(xx*y>x*yy) x=xx,y=yy;
        }
    }
    y*=2;
    ll g=__gcd(x,y);
    x/=g,y/=g;
    if(y==1) printf("%lld\n",x);
    else printf("%lld/%lld\n",x,y);
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 229ms, 内存消耗: 4348K, 提交时间: 2018-07-07 22:41:10

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define MAXN 1000005
ll x,y,g,u,v;
int n,i,j,a[MAXN],s[MAXN],t;
ll gcd(ll x,ll y)
{
	if(!y)return x;
	return gcd(y,x%y);
}
int main()
{
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",a+i);
	for(i=1;i<=n;i++)
	{
		while(t>1&&(ll)(a[i]-a[s[t]])*(s[t]-s[t-1])<=(ll)(a[s[t]]-a[s[t-1]])*(i-s[t]))t--;
		s[++t]=i;
	}
	x=0;
	y=1;
	for(i=1;i<t;i++)for(j=s[i];j<=s[i+1];j++)
	{
		u=(ll)(a[j]-a[s[i]])*(s[i+1]-s[i])-(ll)(a[s[i+1]]-a[s[i]])*(j-s[i]);
		if(u<0)u=-u;
		v=s[i+1]-s[i];
		if(u*y>x*v)
		{
			x=u;
			y=v;
		}
	}
	y*=2;
	g=gcd(x,y);
	x/=g;
	y/=g;
	if(y==1)cout<<x<<endl;
	else cout<<x<<'/'<<y<<endl;
	return 0;
}

上一题