zoukankan      html  css  js  c++  java
  • 【BZOJ 1049】 1049: [HAOI2006]数字序列 (LIS+动态规划)

    1049: [HAOI2006]数字序列

    Description

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

    Input

      第一行包含一个数n,接下来n个整数按顺序描述每一项的键值。n<=35000,保证所有数列是随机的

    Output

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

    Sample Input

    4
    5 2 3 5

    Sample Output

    1
    4

    HINT

    Source

    【分析】  

      首先先每个数减去标号,变成<=的问题。

      第一问显然是LIS。用传统nlogn打法就好了。

      第二问,明显DP转移方程为:

          g[i]=min{g[j]+cost(j,i)|f[j]+1==f[i]}

      问题还是求cost(j,i)

      如果满足f[j]+1==f[i],那么中间的元一定要不>=a[i],要不<=a[j]。

      画个图想一想就知道一定有一个最优解是前半部分等于a[j],后半部分等于a[i]。

      

      本来以为这题和上一题BZOJ 1367有异曲同工之妙,事实上这题要简单很多的啊ORZ。。。

      只要后面好好搞,其实随机数据没有n^3,所以可以过!!、

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 using namespace std;
     7 #define Maxn 35010
     8 #define INF 0xfffffff
     9 #define LL long long
    10 
    11 int a[Maxn],f[Maxn],g[Maxn];
    12 int n;
    13 
    14 int myabs(int x) {return x<0?-x:x;}
    15 int mymin(int x,int y) {return x<y?x:y;}
    16 LL mymin(LL x,LL y) {return x<y?x:y;}
    17 
    18 int ffind(int l,int r,int x)
    19 {
    20     while(l<r)
    21     {
    22         int mid=(l+r+1)>>1;
    23         if(g[mid]<=x) l=mid;
    24         else r=mid-1;
    25     }
    26     return l;
    27 }
    28 
    29 void LIS()
    30 {
    31     int l=0,r=0;
    32     g[0]=-INF;
    33     for(int i=1;i<=n;i++)
    34     {
    35         if(a[i]>=g[r])
    36         {
    37             g[++r]=a[i];
    38             f[i]=r;
    39         }
    40         else
    41         {
    42             int x=ffind(l,r,a[i]);
    43             g[x+1]=a[i];
    44             f[i]=x+1;
    45         }
    46     }
    47     printf("%d
    ",n-r);
    48 }
    49 
    50 struct node
    51 {
    52     int x,y,next;
    53 }t[Maxn];int len;
    54 
    55 int first[Maxn];
    56 void ins(int x,int y)
    57 {
    58     t[++len].x=x;t[len].y=y;
    59     t[len].next=first[x];first[x]=len;
    60 }
    61 
    62 LL h[Maxn],s1[Maxn],s2[Maxn];
    63 
    64 void get_ans()
    65 {
    66     len=0;
    67     memset(first,0,sizeof(first));
    68     for(int i=0;i<=n;i++)
    69     {
    70         ins(f[i],i);
    71     }
    72     memset(h,127,sizeof(h));
    73     h[0]=0;
    74     for(int i=1;i<=n;i++)
    75      for(int j=first[f[i]-1];j;j=t[j].next)
    76      {
    77          int y=t[j].y;
    78          if(y>i) continue;
    79          if(a[y]>a[i]) continue;
    80          s1[y]=0;
    81          for(int k=y+1;k<i;k++) s1[k]=s1[k-1]+myabs(a[k]-a[y]);
    82          s2[i]=0;
    83          for(int k=i-1;k>y;k--) s2[k]=s2[k+1]+myabs(a[k]-a[i]);
    84          for(int k=y;k<i;k++) h[i]=mymin(h[i],h[y]+s1[k]+s2[k+1]);
    85      }
    86     printf("%lld
    ",h[n]);
    87 }
    88 
    89 int main()
    90 {
    91     scanf("%d",&n);
    92     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    93     for(int i=1;i<=n;i++) a[i]-=i;
    94     a[0]=-INF;a[++n]=INF;
    95     LIS();
    96     get_ans();
    97     return 0;
    98 }
    View Code

    2017-01-17 10:33:31

  • 相关阅读:
    【C语言】中的版本规范(C89 C99等)
    【微机】计算机系统组成
    【微机】验证负数以补码存储程序 C语言
    katalon studio升级到6.3.3版本后如何生成测试报告
    使用Katalon Studio进行数据驱动测试的方法(转)
    katalon 参数化
    Katalon中的测试对象、用例和套件的命名规范
    转载kalaton故障处理
    Katalon Studio IE浏览器 不好用 无法录制
    Katalon Studio操作界面详细说明(转载)
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6292005.html
Copyright © 2011-2022 走看看