P7962-[NOIP2021]方差【dp,差分】
正題
題目鏈接:https://www.luogu.com.cn/problem/P7962
題目大意
給出一個(gè)長(zhǎng)度為nnn的序列aaa,你每次可以讓一個(gè)ai(1<i<n)=ai?1+ai+1?aia_i(1<i<n)=a_{i-1}+a_{i+1}-a_iai?(1<i<n)=ai?1?+ai+1??ai?,求能變出的最小方差。
1≤n≤400,1≤ai≤6001\leq n\leq 400,1\leq a_i\leq 6001≤n≤400,1≤ai?≤600或1≤n≤104,1≤ai≤501\leq n\leq 10^4,1\leq a_i\leq 501≤n≤104,1≤ai?≤50
解題思路
民間數(shù)據(jù)過了就當(dāng)過了吧
這個(gè)式子顯然我們可以差分之后變成交換相鄰的數(shù),讓所有的數(shù)都減去a1a_1a1?這樣方差不變并且第一個(gè)保證為000,然后我們記差分?jǐn)?shù)組bi=ai+1?aib_i=a_{i+1}-a_ibi?=ai+1??ai?,那么化一下答案的式子就是
n∑i=1nai2?(∑i=1nai)2?n∑i=1n?1(∑j=1ibj)2?(∑i=1n?1bi(n?i))2n\sum_{i=1}^na_i^2-\left(\sum_{i=1}^na_i\right)^2\Rightarrow n\sum_{i=1}^{n-1}\left(\sum_{j=1}^{i}b_j\right)^2-\left(\sum_{i=1}^{n-1}b_i(n-i)\right)^2ni=1∑n?ai2??(i=1∑n?ai?)2?ni=1∑n?1?(j=1∑i?bj?)2?(i=1∑n?1?bi?(n?i))2
這個(gè)式子乍一眼我們看不出什么,但是我們可以得到每個(gè)bib_ibi?對(duì)之間乘積的權(quán)重記為fi,jf_{i,j}fi,j?,會(huì)發(fā)現(xiàn)fi,jf_{i,j}fi,j?是按照i/ji/ji/j相互之間越接近/越接近中間而遞增的,但是依然會(huì)出現(xiàn)一些邊邊的靠近數(shù)對(duì)的情況比中間的不那么靠近數(shù)對(duì)的權(quán)重要高。
一個(gè)直觀的想法是類似于一個(gè)山谷之類的填法,打幾個(gè)表之后不難發(fā)現(xiàn)確實(shí)是從一個(gè)點(diǎn)往兩邊遞增的規(guī)律。
考慮在此基礎(chǔ)上進(jìn)行dpdpdp,考慮在一個(gè)填好的序列的前面/后面加上一個(gè)數(shù)字會(huì)產(chǎn)生的變化,記ansansans為原來的答案,記LLL為題目中給出的nnn(因?yàn)槟壳拔覀冞€沒有放完nnn個(gè)數(shù)字,所以此時(shí)的nnn不一樣),xxx為插入的數(shù)組。
- 插在前面:
L∑i=1n?1(∑j=1ibj+x)2?(nx+∑i=1n?1bi(n?i))2L\sum_{i=1}^{n-1}\left(\sum_{j=1}^{i}b_j+x\right)^2-\left(nx+\sum_{i=1}^{n-1}b_i(n-i)\right)^2Li=1∑n?1?(j=1∑i?bj?+x)2?(nx+i=1∑n?1?bi?(n?i))2
?ans+Lnx2+2Lx∑i=1n?1bj?2nx∑i=1n?1bi(n?i)?n2x2\Rightarrow ans+Lnx^2+2Lx\sum_{i=1}^{n-1}b_j-2nx\sum_{i=1}^{n-1}b_i(n-i)-n^2x^2?ans+Lnx2+2Lxi=1∑n?1?bj??2nxi=1∑n?1?bi?(n?i)?n2x2 - 插在后面:
L(∑i=1n?1(∑j=1ibj)2+(x+∑i=1n?1bi)2)?(x+∑i=1n?1bi+∑i=1n?1bi(n?i))2L\left(\sum_{i=1}^{n-1}\left(\sum_{j=1}^{i}b_j\right)^2+\left(x+\sum_{i=1}^{n-1}b_i\right)^2\right)-\left(x+\sum_{i=1}^{n-1}b_i+\sum_{i=1}^{n-1}b_i(n-i)\right)^2L???i=1∑n?1?(j=1∑i?bj?)2+(x+i=1∑n?1?bi?)2????(x+i=1∑n?1?bi?+i=1∑n?1?bi?(n?i))2
?ans+L(x+∑i=1n?1bi)2?(x+∑i=1n?1bi)2?2(x+∑i=1n?1bi)(∑i=1n?1bi(n?i))\Rightarrow ans+L\left(x+\sum_{i=1}^{n-1}b_i\right)^2-\left(x+\sum_{i=1}^{n-1}b_i\right)^2-2\left(x+\sum_{i=1}^{n-1}b_i\right)\left(\sum_{i=1}^{n-1}b_i(n-i)\right)?ans+L(x+i=1∑n?1?bi?)2?(x+i=1∑n?1?bi?)2?2(x+i=1∑n?1?bi?)(i=1∑n?1?bi?(n?i))
然后會(huì)發(fā)現(xiàn)我們很難知道∑i=1n?1bi(n?i)\sum_{i=1}^{n-1}b_i(n-i)∑i=1n?1?bi?(n?i)這個(gè)東西,所以考慮放進(jìn)dpdpdp數(shù)組里面維護(hù),但是如果丟進(jìn)去維護(hù)了后面那個(gè)東西就完全沒有必要了,所以可以刪掉很多復(fù)雜的部分。
那么設(shè)fi,jf_{i,j}fi,j?表示目前填了iii個(gè)∑i=1n?1bi(n?i)=j\sum_{i=1}^{n-1}b_i(n-i)=j∑i=1n?1?bi?(n?i)=j時(shí)的最小方差,然后就可以O(1)O(1)O(1)轉(zhuǎn)移了。
這樣的時(shí)間復(fù)雜度是O(n2ai)O(n^2a_i)O(n2ai?)的,可以拿到888888分,我在考場(chǎng)上就止步于此了。
現(xiàn)在來分析一下最后一個(gè)點(diǎn)ai≤50a_i\leq 50ai?≤50的性質(zhì),也就是說差分?jǐn)?shù)組里面最多只有505050個(gè)數(shù)是有值的,所以有一堆000,直接動(dòng)態(tài)更新dpdpdp枚舉的上界就過了。
時(shí)間復(fù)雜度:O(naimin?{ai,n})O(na_i\min\{a_i,n\})O(nai?min{ai?,n})
好不容易那么接近一次正解,你卻讓我輸?shù)哪敲磸氐?#xff0c;焯!\color{white}好不容易那么接近一次正解,你卻讓我輸?shù)哪敲磸氐?#xff0c;焯!好不容易那么接近一次正解,你卻讓我輸的那么徹底,焯!
code
#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 */總結(jié)
以上是生活随笔為你收集整理的P7962-[NOIP2021]方差【dp,差分】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 角速度单位 角速度介绍
- 下一篇: 彩排的意思 何谓彩排