CC's

Back

艹了天天都被不知道的知识点教育,知道的又做不出来。 :lei:

在动态规划中,决策单调性指对于j<jj < j'f(j)f(j')的最佳转移f(i)f(i')位置ii'一定不小于f(j)f(j)ii

假设

f(r)=minf(k1)+w(k,r)f(r)=\min{f(k-1)+w(k,r)}

为了证明这一点,首先假设

f(r)=f(k1)+w(k,r)f(r)=f(k-1)+w(k,r)

此时我们有i<k\forall i < k

f(k1)+w(k,r)<f(i1)+w(i,r)f(k-1)+w(k,r) < f(i-1)+w(i,r)

此后,将r后挪1。我们必须要证明i<k\forall i < k

f(k1)+w(k,r+1)<f(i1)+w(i,r+1)f(k-1)+w(k,r+1) < f(i-1)+w(i,r+1)

也就是证明对于两边的两个增量Δ\Delta

w(k,r+1)w(k,r)<w(i,r+1)w(i,r)w(k,r+1) - w(k,r) < w(i,r+1) - w(i,r)

使用分治#

一旦有决策单调性了,我们就可以通过优于n2n^2的总复杂度完成规划。

例如使用分治。当我们找到区间[l,r][ l, r ]的中点mm的决策点pp时,那么[l,m1][l, m-1]区间只能从不晚于pp转移,[m+1,r][m+1, r]只能从不早于pp转移。

l和r是当前要决策的区间,L和R是转移位置。

void solve(int l,int r,int L,int R) {
    if(l>r)return;
    int mid=(l+r)/2;
    int p=0;
    for(int i=L;i<=min(mid,R);i++){
        //这里的下标写法要和方程配套
        if(f[i-1]+w[i,mid]<f[mid]){
            f[mid]=f[i-1]+w[i,mid];
            p=i;
        }
    }
    solve(l,mid-1,L,p);
    solve(mid+1,r,p,R);
}
cpp

【CF868F】yts1999 Doing Minimization#

You are given an array of n integers a1… an. The cost of a subsegment is the number of unordered pairs of distinct indices within the subsegment that contain equal elements. Split the given array into k non-intersecting non-empty subsegments so that the sum of their costs is minimum possible. Each element should be present in exactly one subsegment.

分析#

f(i,j)f(i,j)表示前j个分i段。

这个题目就满足决策单调。一个更长的区间+1之后只有可能比短的区间增加更多的代价。

接下来的问题是怎么算这道题里的w(i,j)w(i,j)n2n^2显然不行。看到有人整了个类似莫队的东西,不过我还没太弄明白这个复杂度是怎么算的,看起来是和分治的内层循环一致所以就对复杂度没有更多的贡献了。

一共进行k轮分治,O(knlogn)O(kn\log n)

一点点决策单调性
https://astro-pure.js.org/blog/juece-dandiao
Author Cheng Chen
Published at 2020年3月23日
Comment seems to stuck. Try to refresh?✨