zoukankan      html  css  js  c++  java
  • bzoj1049[HAOI2006]数字序列

    1049: [HAOI2006]数字序列

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1813  Solved: 789
    [Submit][Status][Discuss]

    Description

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

    Input

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

    Output

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

    Sample Input

    4
    5 2 3 5

    Sample Output

    1
    4

     

    被细节恶心到啦。
    第一问可以补集转换,减下标然后求最长不下降子序列,用总序列长度-lis长度水过,关键是这个第二问呐。。
    有个并不显然的显然结论:
    若j<i&&f[j]+1==f[i]&&a[j]<=a[i](保证j可以转移到i)
    那么把这段区间中的数值改成a[j]或者a[i]一定是最优的,跑个dp决策

    这里有证明
    http://pan.baidu.com/share/link?uk=2651016602&shareid=1490516411

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define N 35005
     4 using namespace std;
     5 int n,mx,a[N],b[N],f[N],hd[N],nxt[N];ll g[N],s1[N],s2[N];
     6 int find(int x){
     7     int l=1,r=mx,mid,ans=0;
     8     while(l<=r){
     9         if(b[mid=(l+r)>>1]<=x)l=(ans=mid)+1;
    10         else r=mid-1;
    11     }return ans;
    12 }
    13 void dp(){
    14     memset(b,0x3f,sizeof(b));
    15     b[0]=-1<<30;
    16     for(int i=1;i<=n;i++){
    17         int p=find(a[i]);
    18         mx=max(mx,f[i]=p+1);
    19         b[p+1]=min(b[p+1],a[i]);
    20     }
    21 }
    22 void add(int x,int y){nxt[y]=hd[x];hd[x]=y;}
    23 void solve(){
    24     //memset(g,0x3f,sizeof(g));g[0]=0;
    25     for(int i=1;i<=n;i++)g[i]=1ll<<60;
    26     memset(hd,-1,sizeof(hd));
    27     for(int i=n;i>=0;i--)add(f[i],i);
    28     for(int i=1;i<=n;i++){
    29         for(int j=hd[f[i]-1];~j&&j<i;j=nxt[j]){
    30             if(a[j]>a[i])continue;
    31             for(int k=j;k<=i;k++)
    32             s1[k]=abs(a[k]-a[j]),s2[k]=abs(a[k]-a[i]);
    33             for(int k=j+1;k<=i;k++)
    34             s1[k]+=s1[k-1],s2[k]+=s2[k-1];
    35             for(int k=j;k<i;k++)
    36             g[i]=min(g[i],g[j]+s1[k]-s1[j]+s2[i]-s2[k]);
    37         }
    38     }
    39 }
    40 int main(){
    41     scanf("%d",&n);a[0]=-1<<30;
    42     for(int i=1;i<=n;i++)
    43     scanf("%d",&a[i]),a[i]-=i;
    44     a[++n]=1<<30;
    45     dp();solve();
    46     printf("%d
    %lld
    ",n-mx,g[n]);
    47     return 0;
    48 }
  • 相关阅读:
    【Linux】Mac PD set centos static ip
    【Linux】Set CentOS no GUI default
    【QT】qt python install pip
    【QT】Installer requires Xcode Version 5.0.0 for Qt download if toolchain not found
    【Solution】idea中dtd没有找到
    【Mac】-NO.161.Mac.1 -【MacOS Error running 'Tomcat 8.5.371': Cannot run program Permission denied】
    【Eclipse】-NO.163.Eclipse.1 -【Eclipse springboot 1.x 创建maven工程初始化报错】
    C----循环
    scrapy库安装
    C----框架、变量、常量、赋值、复合赋值、初始化、表达式、运算符
  • 原文地址:https://www.cnblogs.com/wsy01/p/8324600.html
Copyright © 2011-2022 走看看