zoukankan      html  css  js  c++  java
  • BZOJ 1049 数字序列

    Description

    现在我们有一个长度为n的整数序列A。但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列。但是不希望改变过多的数,也不希望改变的幅度太大。

    Input

    第一行包含一个数n,接下来n个整数按顺序描述每一项的键值。

    Output

    第一行一个整数表示最少需要改变多少个数。 第二行一个整数,表示在改变的数最少的情况下,每个数改变的绝对值之和的最小值。

    Sample Input

    4
    5 2 3 5

    Sample Output

    1
    4

    HINT

    【数据范围】

    90%的数据n<=6000。

    100%的数据n<=35000。

    保证所有数列是随机的。

    Source

    这道题感觉太神了。

    令原数组为a。

    对于第一问我们可以反过来思考——要求最少的改动的,不就是求最多的不改动的吗?

    f[i]表示前i位最多的不改动的数字个数,f[i]=max(f[j]+1),j需要满足a[i]-a[j]≥i-j。对于条件,我们移一下项,化为a[i]-i≥a[j]-j,令b[i]=a[i]-i,不就是b[i]≥b[j]。细心的朋友一定看出来了,这不就是最长不下降子序列吗!!!O(nlogn)的求法上起。

    第二问稍微麻烦一点,我们要知道一个结论:另g[i]表示前i个数,在改动数最少的前提下,最少改动的值。

    那么对于所有合法的转移i,j(i>j,f[i]=f[j]+1,b[i]≥b[j]),最优解一定是在i与j之间某个k,k到j的值全为b[j],k+1到i的值全为b[i]。因此就可以dp了。证明自己脑补一下就可以了。。。(自己画画图,根据条件想想应该是可以明白的)

     1 #include<cstring>
     2 #include<vector>
     3 #include<algorithm>
     4 #include<iostream>
     5 #include<cstdio>
     6 #include<cstdlib>
     7 using namespace std;
     8 
     9 #define inf (1<<30)
    10 #define maxn 35010
    11 int tree[maxn],tot,n,f[maxn],a[maxn],bac[maxn];
    12 long long g[maxn],s1[maxn],s2[maxn];
    13 vector <int> vec[maxn];
    14 
    15 inline int lowbit(int x) { return x & -x; }
    16 
    17 inline void change(int a,int b) { for (;a <= tot;a += lowbit(a)) tree[a] = max(tree[a],b); }
    18 
    19 inline int calc(int a) { int ret = 0; for (;a;a -= lowbit(a)) ret = max(ret,tree[a]); return ret; }
    20 
    21 int main()
    22 {
    23     freopen("1049.in","r",stdin);
    24     freopen("1049.out","w",stdout);
    25     scanf("%d",&n);
    26     for (int i = 1;i <= n;++i) scanf("%d",a+i),a[i] -= i,bac[++tot] = a[i];
    27     a[++n] = inf; bac[++tot] = a[n];
    28     sort(bac+1,bac+tot+1); tot = unique(bac+1,bac+tot+1) - bac - 1;
    29     for (int i = 1;i <= n;++i)
    30     {
    31         int pos = lower_bound(bac+1,bac+tot+1,a[i]) - bac;
    32         f[i] = calc(pos) + 1;
    33         change(pos,f[i]);
    34     }
    35     printf("%d
    ",n-f[n]);
    36     for (int i = 0;i <= n;++i) vec[f[i]].push_back(i);
    37     a[0] = -inf;
    38     memset(g,0x7,sizeof(g)); g[0] = 0;
    39     for (int i = 1;i <= n;++i)
    40     {
    41         int nn = vec[f[i] - 1].size();
    42         for (int p = 0;p < nn;++p)
    43         {
    44             int j = vec[f[i]-1][p];
    45             if (j >= i) break; if (a[i] < a[j]) continue;
    46             for (int k = j;k <= i;++k) s1[k]=abs(a[k]-a[j]),s2[k]=abs(a[k]-a[i]);
    47             for (int k = j+1;k <= i;++k) s1[k] += s1[k-1],s2[k] += s2[k-1];
    48             for (int k = j;k < i;++k) g[i] = min(g[i],g[j]+s1[k]-s1[j]+s2[i]-s2[k]);
    49         }
    50     }
    51     printf("%lld",g[n]);
    52     fclose(stdin); fclose(stdout);
    53     return 0;
    54 }
    View Code
  • 相关阅读:
    Editor REST Client
    log配置
    spring-boot-configuration-processor
    http请求
    做项目用到的一些正则表达式,贴出来共享
    批量插入的实现
    sql执行顺序对比
    Java常用的并发工具类:CountDownLatch、CyclicBarrier、Semaphore、Exchanger
    spring中bean的生命周期
    多属性的对象列表的两种排序方法
  • 原文地址:https://www.cnblogs.com/mmlz/p/4294117.html
Copyright © 2011-2022 走看看