zoukankan      html  css  js  c++  java
  • BZOJ 1049 [HAOI2006]数字序列 DP

    第一问:最长xx子序列

    第二问:f[i]表示前i个的最少花费,可以从满足条件j(假设以a[i]结尾的最长xx组序列长度为len,则j需要满足以a[j]结尾的最长xx组序列长度为len-1)

    方法:记录最长xx子序列的转移,邻接表存,然后枚举每个转移。

    ps:有个结论:如果从j转移到i的话,那么中间一定有一个k(k>=j&&k<i),使得j~k的高度都是a[j],k+1~i的高度都是i,且这样的花费是最优的,很容易想明白的~

    这个暴力显然tle,怎么可能会ac?

    数据弱,不解释

    View Code
     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <cstdio>
     5 #include <algorithm>
     6 
     7 #define N 55555
     8 #define INF 1LL<<60
     9 
    10 using namespace std;
    11 
    12 int a[N],c[N];
    13 int n,cnt,len;
    14 int dp[N];
    15 int head[N],next[N],to[N];
    16 long long f[N],sum1[N],sum2[N];
    17 
    18 inline void add(int u,int v)
    19 {
    20     to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++;
    21 }
    22 
    23 inline void read()
    24 {
    25     scanf("%d",&n);
    26     for(int i=1;i<=n;i++)
    27     {
    28         scanf("%d",&a[i]);
    29         a[i]-=i;
    30     }
    31 }
    32 
    33 inline void step1()
    34 {
    35     n++;
    36     a[n]=0x3f3f3f3f; a[0]=-a[n];
    37     for(int i=0;i<=n;i++) c[i]=0x3f3f3f3f;
    38     len=1; c[1]=a[1]; c[0]=-c[0];
    39     dp[0]=0; dp[1]=1;
    40     for(int i=2;i<=n;i++)
    41     {
    42         int x=upper_bound(c,c+1+len,a[i])-c;
    43         len=max(len,x);
    44         c[x]=min(c[x],a[i]);
    45         dp[i]=x;
    46     }
    47     cout<<n-dp[n]<<endl;
    48 }
    49 
    50 inline void step2()
    51 {
    52     memset(head,-1,sizeof head); cnt=0;
    53     for(int i=n;i>=0;i--) add(dp[i],i),f[i]=INF;
    54     f[0]=0;
    55     for(int i=1,tmp;i<=n;i++)
    56         for(int j=head[dp[i]-1];~j;j=next[j])
    57         {
    58             if(to[j]>i) break;
    59             if(a[to[j]]>a[i]) continue;
    60             for(int k=to[j];k<=i;k++) sum1[k]=abs(a[k]-a[to[j]]),sum2[k]=abs(a[k]-a[i]);
    61             for(int k=to[j]+1;k<=i;k++) sum1[k]+=sum1[k-1],sum2[k]+=sum2[k-1];
    62             for(int k=to[j];k<i;k++)
    63                 f[i]=min(f[i],f[to[j]]+sum1[k]-sum1[to[j]]+sum2[i]-sum2[k]);
    64         }
    65     cout<<f[n]<<endl;
    66 }
    67 
    68 inline void go()
    69 {
    70     step1();
    71     step2();
    72 }
    73 
    74 int main()
    75 {
    76     read(),go();
    77     return 0;
    78 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    POJ3683 Priest John's Busiest Day
    POJ3678 Katu Puzzle
    洛谷4782 【模板】2-SAT 问题
    BZOJ2330或洛谷3275 [SCOI2011]糖果
    POJ1236或洛谷2746或洛谷2812 Network of Schools
    POJ2230 Watchcow
    POJ2942 Knights of the Round Table
    POJ3694 Network
    BZOJ1123或洛谷3469 [POI2008]BLO-Blockade
    animition动画的加入
  • 原文地址:https://www.cnblogs.com/proverbs/p/2956820.html
Copyright © 2011-2022 走看看