Codeforces Round #825 (Div. 2) C2. Good Subarrays (Hard Version)

Codeforces Round #825 (Div. 2)C2. Good Subarrays (Hard Version)

题解

\(ans[i]\) 为以 \(i\) 为结尾最长的好的数列长度

观察发现,以 \(i\) 为结尾的好的数列,长度可以是 \(1,2,3,...,ans[i]\)

这个很好理解,因为如果区间数列 \([l,r]\) 是好的,那么 \([l+1,r]\) 一定也是好的。

我们要求的答案也就是 \(\sum ans[i]\)

我们先来考虑 \(ans[i]\) 是怎么求,显然有 \(ans[i]=min(ans[i-1]+1,a[i])\) ,要么在前面的最长的好的数列的基础上往后添一个,要么它最多只能有 \(a[i]\) 的长度。

当强制 \(ans[i]=a[i]\) 然后按照上述方法算出后面的位置的 \(ans\) 时,记 \(sum[i]=\sum_{j=i}^nans[j]\)

\(sum[i]\) 数组也比较好求,倒序求出来,可以借助线段树

考虑修改操作,若修改的位置是 \(x\) ,显然 \(x\) 以前的答案不会改变,若 \(x\) 位置答案变成了新的 \(ans[x]\) ,那么后面的答案会变成形如 \(ans[x]+1,ans[x]+2,...,ans[x]+k-1,a[x+k]\)

找到第一个 \(k\) 满足 \(a[x+k]\le ans[x]+k\)\(ans[x+k]-x-k\le ans[x]-x\) ,那么 \(x\) 及以后的答案就变成了 \(\sum_{i=0}^{k-1}(ans[x]+i)+sum[k]\)

\(k\) 可以用线段树,然后这个题就做完了,时间复杂度 \(O(n\log n)\)

posted @ 2022-10-12 00:38  缙云山车神  阅读(246)  评论(0编辑  收藏  举报