CSP2019 劃分 解題報告

2022-04-07 10:02:08 字數 1736 閱讀 7219

[csp2019] 劃分

有乙個長度為 \(n\) 的序列 \(a_i\)

\((n \le 4 \times 10^7)\), 求

\[(\sum_^ a_i)^2 + (\sum_^ a_i)^2 \dots (\sum_+1}^ a_i)^2

\]的最小值.

結論: 上述式子能取到最小值, 當且僅當最後一塊 (即\(\sum_+1}^ a_i\)) 取到了最小值.

證明: 暫時不會.

那我們就 \(dp\) 保證最後一塊最小就行了.

設 \(val[i]\) 為以 \(i\) 結尾的序列的最後一塊的最小值.

那麼對於每一位 \(i\) 只需從 \(i-1\) 到 \(0\) 找到第一位 \(j\) 滿足 \(sum[i] - sum[j] \ge val[j]\), \(val[i]\) 即為 \(sum[i]-sum[j]\). (\(sum\) 為字首和陣列)

可以發現, 每次 \(j\) 值是有單調性的, 所以可以考慮單調佇列優化.

隊頭的篩選很簡單, 滿足要求就 +1, 找到最後乙個滿足條件的 \(j\) 即可.

再考慮隊尾的處理, 如果只是單純的把當前的 \(i\) 加入佇列中的話, 就會出現 "佇列中後面滿足但前面不滿足的情況",

比如說下面這個例子.

7 0

15 19 14 1 5 7 17

設 \(lst[i]\) 為 \(i\) 的上乙個塊的終點.

在上面這個例子中, \(lst[6]=2\), 那麼 \(i==7\) 時, 隊頭 \(t1\) 就會在 \(2\) 的位置,

但是, 由於 \(lst[3]=1,\ val[3]=33\), 而 \(sum[7]-sum[3]==30 < val[3]\), 所以 \(t1\) 會停在 \(3\).

但是, \(lst[5]=2\), 所以 \(lst[7]\) 實際上是可以取到 \(5\) 的.

所以, 我們可以發現, 要在加入乙個新的選項時, 要去除一些不優情況.

首先想到的是把佇列中 \(val[que[t2]] > val[i]\) 的去掉, ( \(t2\) 為隊尾 )

但是這樣可能會導致後面的一些 \(i\) 取不到滿足要求的 \(j\),

所以我們還要保證當 \(que[t2]\) 對於後面的某個數滿足要求時, \(i\) 也一定滿足要求.

設 \(t\) 為後面的乙個點, 那麼就要滿足: \(sum[t]-sum[que[t2]] \ge val[que[t2]]\) 可以推導到 \(sum[t]-sum[i] \ge val[i]\).

即 $ val[que[t2]] + sum[que[t2]] \ge val[i] + sum[i] $,

那麼, 在把 \(i\) 加入隊尾的時候判斷上述條件, 若滿足則 \(t2--\).

#include#define ll long long

using namespace std;

const int n=5e5+7;

int n,ty,que[n],t1=1,t2,pre[n];

ll a[n],sum[n],val[n],ans;

int main()

que[++t2]=0;

for(int i=1;i<=n;i++)

int p=n;

while(p)

printf("%lld\n",ans);

return 0;

}

CSP2019 劃分 解題報告

csp2019 劃分 有 n 個非負整數 a i n le 4 10 7 將它們分為若干部分,記為 s i 要求 s ge s i 設 res sum s i 2 求 res 的最小值 考場上寫的做法.設 f i j 為第一段的起點為 i 終點為 j 時 res 的最小值.樸素做法直接列舉 i,j,...

CSP2019 樹的重心 解題報告

csp2019 樹的重心 t 組資料 1 le t le 5 每次給定一棵 n 個點的樹 1 le n le 299995 設 e 為樹的邊集,v x,v y 分別為刪去邊 x,y 後 點 x 所在的點集和點 y 所在的點集.求 sum left sum x 是 v x 的重心 x sum y 是 ...

CSP2019 JX 散步 解題報告

csp2019 jx 散步 有乙個長度為 l 的環 2 le l le 10 9 環上有 n 個人,m 個出口 1 le n,m le 2 times 10 5 規定第乙個出口的位置為 0 並將 到第乙個出口的距離 定義為 從順時針方向走到第乙個路口所走的路程 每個人有兩個屬性 t i,x i 分別...