• BZOJ1049 [HAOI2006]数字序列0


    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

       

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

      

    Description

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

    Input

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

    Output

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

    Sample Input

    4
    5 2 3 5

    Sample Output

    1
    4
     
     
    正解:DP
    解题报告:
      考虑补集转换,题目转换为:最大化不修改的点。
      对于任意的i,j(j<i),如果可以通过修改中间的j-i+1个数来使得[j,i]满足要求,必要条件是a[i]-a[j]>=i-j,不妨设b[i]=a[i]-i,则条件变为b[i]>=b[j],至此第一问最长不降子序列可做。
      第二问,不妨设g[i]为1到i的答案,则
      $${g[i]=min(g[j]+cost[j+1,i])}$$
      j需要满足:j可以转移到i且$${f[j]+1=f[i]}$$
      cost[j,i]表示修改[j,i]的最小代价
      结论:必定存在点t使得[j,t]都为bj,[t+1,i]都为bi。证明从略
      只需每次找到一个分割点,暴力枚举即可。细节较多。
     
     1 //It is made by ljh2000
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <algorithm>
     8 #include <vector>
     9 #include <string>
    10 using namespace std;
    11 typedef long long LL;
    12 const int MAXN = 35011;
    13 const LL inf = (1LL<<50);
    14 int n;
    15 LL a[MAXN],g[MAXN],cost1[MAXN],cost2[MAXN],b[MAXN],c[MAXN],ans,f[MAXN];
    16 vector<int>w[MAXN];
    17 inline int getint(){
    18     int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
    19     if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
    20 }
    21 inline int find(LL x){ int l=1,r=n,pos=0,mid; while(l<=r) { mid=(l+r)>>1; if(c[mid]<=x) l=mid+1,pos=mid; else r=mid-1; } return pos; }
    22 inline void work(){
    23     n=getint(); for(int i=1;i<=n;i++) a[i]=getint(),b[i]=a[i]-i; a[++n]=inf; b[n]=a[n]-n; for(int i=1;i<=n;i++) c[i]=g[i]=inf;
    24     for(int i=1;i<=n;i++) f[i]=find(b[i])+1,c[f[i]]=min(c[f[i]],b[i]); for(int i=1;i<=n;i++) ans=max(ans,f[i]);
    25     printf("%lld
    ",n-ans); w[0].push_back(0); int from; LL now; b[0]=-inf;//!!!
    26     for(int i=1;i<=n;i++) {
    27         from=f[i]-1;
    28         for(int j=0,size=w[from].size();j<size;j++) {
    29             int v=w[from][j]; if(b[i]<b[v]) continue;//转移不到           
    30             cost1[v-1]=cost2[v-1]=0;
    31             for(int k=v;k<=i;k++) cost1[k]=abs(b[k]-b[v]),cost2[k]=abs(b[k]-b[i]);
    32             for(int k=v+1;k<=i;k++) cost1[k]+=cost1[k-1],cost2[k]+=cost2[k-1];           
    33             for(int k=v;k<=i;k++) { 
    34                 now=cost1[k]-cost1[v]+cost2[i]-cost2[k]; 
    35                 g[i]=min(g[i],g[v]+now);
    36             }
    37         }
    38         w[f[i]].push_back(i);
    39     }
    40     printf("%lld",g[n]);
    41 }
    42 
    43 int main()
    44 {
    45     work();
    46     return 0;
    47 }
  • 相关阅读:
    10.18.2 linux文件压缩与打包
    动态代理与静态代理的区别
    JAVA的Date类与Calendar类
    【面试题001】类型转换关键字,空类对象模型,拷贝构造函数,赋值运算符函数
    【面试题001】类型转换关键字,空类对象模型,拷贝构造函数,赋值运算符函数
    j2EE经典面试题
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6193204.html
Copyright © 2020-2023  润新知