P7962-[NOIP2021]方差【dp,差分】

1|0正题

题目链接:https://www.luogu.com.cn/problem/P7962


1|1题目大意

给出一个长度为n的序列a,你每次可以让一个ai(1<i<n)=ai1+ai+1ai,求能变出的最小方差。

1n400,1ai6001n104,1ai50


1|2解题思路

民间数据过了就当过了吧

这个式子显然我们可以差分之后变成交换相邻的数,让所有的数都减去a1这样方差不变并且第一个保证为0,然后我们记差分数组bi=ai+1ai,那么化一下答案的式子就是

ni=1nai2(i=1nai)2ni=1n1(j=1ibj)2(i=1n1bi(ni))2

这个式子乍一眼我们看不出什么,但是我们可以得到每个bi对之间乘积的权重记为fi,j,会发现fi,j是按照i/j相互之间越接近/越接近中间而递增的,但是依然会出现一些边边的靠近数对的情况比中间的不那么靠近数对的权重要高。

一个直观的想法是类似于一个山谷之类的填法,打几个表之后不难发现确实是从一个点往两边递增的规律。

考虑在此基础上进行dp,考虑在一个填好的序列的前面/后面加上一个数字会产生的变化,记ans为原来的答案,记L为题目中给出的n(因为目前我们还没有放完n个数字,所以此时的n不一样),x为插入的数组。

  • 插在前面:

Li=1n1(j=1ibj+x)2(nx+i=1n1bi(ni))2

ans+Lnx2+2Lxi=1n1bj2nxi=1n1bi(ni)n2x2

  • 插在后面:

L(i=1n1(j=1ibj)2+(x+i=1n1bi)2)(x+i=1n1bi+i=1n1bi(ni))2

ans+L(x+i=1n1bi)2(x+i=1n1bi)22(x+i=1n1bi)(i=1n1bi(ni))

然后会发现我们很难知道i=1n1bi(ni)这个东西,所以考虑放进dp数组里面维护,但是如果丢进去维护了后面那个东西就完全没有必要了,所以可以删掉很多复杂的部分。

那么设fi,j表示目前填了ii=1n1bi(ni)=j时的最小方差,然后就可以O(1)转移了。

这样的时间复杂度是O(n2ai)的,可以拿到88分,我在考场上就止步于此了。

现在来分析一下最后一个点ai50的性质,也就是说差分数组里面最多只有50个数是有值的,所以有一堆0,直接动态更新dp枚举的上界就过了。
时间复杂度:O(naimin{ai,n})


1|3code

#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=5e5+10,inf=1e18; ll n,L,a[N],s[N],f[2][N],ans; signed main() { scanf("%lld",&n); if(n==1)return puts("0"); for(ll i=1;i<=n;i++)scanf("%lld",&a[i]); L=n*a[n];ans=inf; for(ll i=1;i<n;i++)a[i]=a[i+1]-a[i]; n--;sort(a+1,a+1+n);L=a[1]; for(ll i=1;i<=n;i++)s[i]=s[i-1]+a[i]; for(ll i=0;i<=L;i++)f[1][i]=inf; f[1][a[1]]=a[1]*a[1]; for(ll k=2;k<=n;k++){ int R=s[k]*k; for(ll i=0;i<=R;i++)f[k&1][i]=inf; for(ll i=0;i<=L;i++){ if(f[~k&1][i]!=inf){ f[k&1][i+a[k]*k]=min(f[k&1][i+a[k]*k],f[~k&1][i]+k*a[k]*a[k]+2ll*i*a[k]); f[k&1][i+s[k]]=min(f[k&1][i+s[k]],f[~k&1][i]+s[k]*s[k]); } } L=R; } for(ll i=0;i<=L;i++) if(f[n&1][i]!=inf) ans=min(ans,f[n&1][i]*(n+1)-i*i); printf("%lld\n",ans); return 0; } /* 10 6 19 34 35 56 63 82 82 83 99 */

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/15589296.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(183)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示