码迷,mamicode.com
首页 > 其他好文 > 详细

[HAOI2006] 数字序列 - dp,二分

时间:2020-02-29 18:40:47      阅读:49      评论:0      收藏:0      [点我收藏+]

标签:cout   额外   for   abs   i++   long   lin   构造   复杂度   

现在我们有一个长度为n的整数序列A。但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列。但是不希望改变过多的数,也不希望改变的幅度太大。求在改变的数最少的情况下,每个数改变的绝对值之和的最小值。

\(n\leq 35000\),保证数据随机

Solution

第一问很容易,只需要令 \(b_i=a_i-i\),然后跑最长不下降子序列即可

下面考虑第二问,令 \(f[i]\) 表示前 \(i\) 个数构成的数列要变成单调上升需要改动的最小幅度

\(a_i,a_j, i<j\) 满足 \(a_j-a_i \geq j-i\),则 \([i,j]\) 中一定存在一个 \(k\),使得 \(a[i\dots k]\) 都变成 \(a[i]\)\(a[k+1\dots j]\) 都变成 \(a[j]\),整个序列上升并且花费的代价最小,暴力枚举 \(j,k\) 来转移,时间复杂度为 \(O(n^3)\)

  • 证明可以通过任意构造一种最优解形态,然后通过代价不变的转化使其变化为上述形态

考虑转移到 \(f[i]\) 的决策点 \(j<i\) 要求第一问中的 \(g[j]+1=g[i]\),因此转移点的总数是 \(O(n)\)\(O(n\sqrt n)\) 量级的,且 \(w\) 的区间期望为 \(O(\sqrt n)\),总体复杂度估计为 \(O(n\sqrt n)\)\(O(n^2)\) 之间

在数组前后额外添加最大最小值,可以提供类似于超级源汇的功能

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1000005;
int n,a[N],b[N],f[N],g[N],h[N];
vector <int> v[N];
int myabs(int x) {return x>0?x:-x;}
signed main() {
    ios::sync_with_stdio(false);
    cin>>n;
    a[0]=b[0]=-1e9;a[n+1]=b[n+1]=1e9;
    for(int i=1;i<=n;i++) {
        cin>>a[i];
        b[i]=a[i]-i;
    }
    ++n;
    h[1]=b[1]; g[1]=1;
    int len=1;
    for(int i=2;i<=n;i++) {
        int pos=upper_bound(h+1,h+len+1,b[i])-h-1;
        if(pos==len) {
            ++len;
            h[len]=b[i];
            g[i]=len;
        }
        else {
            ++pos;
            h[pos]=b[i];
            g[i]=pos;
        }
    }
    for(int i=1;i<=n;i++) v[g[i]].push_back(i);
    v[0].push_back(0);
    f[0]=0;
    for(int i=1;i<=n;i++) {
        f[i]=1e9;
        for(int j:v[g[i]-1]) if(j<=i&&b[i]>=b[j]) {
            int tmp=0;
            for(int k=j;k<=i;k++) tmp+=myabs(b[i]-b[k]);
            for(int k=j;k<i;k++) {
                tmp-=myabs(b[i]-b[k]);
                tmp+=myabs(b[j]-b[k]);
                f[i]=min(f[i],tmp+f[j]);
            }
        }
    }
    cout<<n-len<<endl<<f[n]<<endl;
}

[HAOI2006] 数字序列 - dp,二分

标签:cout   额外   for   abs   i++   long   lin   构造   复杂度   

原文地址:https://www.cnblogs.com/mollnn/p/12384566.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!