题解 P5665 【划分【民间数据】】

2019-11-17 00:00:00 题解

乱搞笔记 by ChanHacker

我的博客:https://ch66.cf/ 欢迎来踩 这题瞎写就可以了,大暴力,单调栈都不需要。 我还以为有多难呢

我们设$ f[i] $为前i个数,$O(n)$的枚举$j$,$i-j$的区间合并,复杂度$O(n^2)$

然后找规律。。。。

发现当$j<=i$时,决策i一定大于等于决策j

于是$O(n)$算法诞生了 下面是代码(考试的时候没打高精)
#include<bits/stdc++.h>
using namespace std;

long long read() {
    register long long x=1,ans=0;register char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-') x*=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){ans=(ans<<3)+(ans<<1)+ch-48;ch=getchar();}
    return x*ans;
}

const long long N=40000005;
long long n,a[N],f[N],num[N],sum[N];

int main() {
    n=read(); long long type=read();
    if(type==0) {
        for(register int i=1;i<=n;++i) {
            a[i]=read(); sum[i]=sum[i-1]+a[i];
        }
    }
    memset(f,0,sizeof(f)); f[0]=0;
    memset(f,0x3f,sizeof(f)); f[0]=0;
    int ans=0;
    for(register int i=1;i<=n;++i) {
        for(register int j=ans;j<i;++j) {
            if(num[j]<=sum[i]-sum[j]) {
                if(f[j]+(sum[i]-sum[j])*(sum[i]-sum[j])<=f[i]) {
                    ans=j;
                    f[i]=f[j]+(sum[i]-sum[j])*(sum[i]-sum[j]);
                    num[i]=sum[i]-sum[j];
                }
            }
        }
//      if(ans<lst) cout<<"Error"<<' '<<ans<<' '<<res<<endl;
    //  if(a[i]==1) cout<<f[i-1]<<' '<<f[i]<<endl;
    }
    cout<<f[n]<<endl;
    return 0;
}
发题解不易,今天的Rp不易,希望各位看到这里的巨老给本蒟蒻留一个赞 2019.11.17