zoukankan      html  css  js  c++  java
  • bzoj4621: Tc605

    应要求写一下这个题的题解。

    我的DP很奥(奇)妙(怪),不过跟标算还是殊途同归的(反正怎么做都行……)

    先讲一下奥妙的性质吧。

    首先,在最终序列中,每个数最多出现一段,并且,对于出现的数,每段数两两之间的相对位置相较原序列保持不变。

    然后,你还可以发现,一个数可以延伸到最左的左端点、和最右的右端点,这些都是可以算出来的。

    如果我们不考虑操作次数的限制,这个问题就变成了,按顺序给你一堆区间,让你在每个区间里选一小段,使选出来的区间不重叠地覆盖整个序列,并且区间之间的相对位置要按照给定的顺序。

    下面考虑次数限制,可以发现,对于一个合法的目标序列(合法的意思就是符合前面的要求,对应到题目就是能够通过操作得到),最优的操作方案显然是按由小到大的顺序对每个数进行操作,并且对每个数之多操作1次。

    进一步考虑,发现,对于一个数,我们不需要对它进行操作,当且仅当该数不在最终序列中出现,或者该数在最终序列中出现的位置恰好仅为该数在原序列中的位置。

    换句话说,操作k次就是限制了,你的最终序列只能有k段数(如果一个数只在原序列出现的位置出现,那么就不算一段数,需要特判)

    之后就是dp,令dp[k][i]表示现在已经有k段数,并且当前计算到原序列左起第i个数的段。

    作者太懒了,反正是普及组DP,你们自己脑补好了,那个特判还是要想一想的(对于我这种老年选手)。

    (我觉得我已经说得很详细了啊TaT)

    (嘛...主要是好困想碎叫QuQ)

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <algorithm>
    #define ll long long
    #define N 505
    #define P 1000000007
     
    using namespace std;
    inline int read(){
        int ret=0;char ch=getchar();
        while (ch<'0'||ch>'9') ch=getchar();
        while ('0'<=ch&&ch<='9'){
            ret=ret*10-48+ch;
            ch=getchar();
        }
        return ret;
    }
     
    int kk;
    int n,a[N];
    int l[N],r[N];
    int dp[N][N],dlt[N];
     
    int main(){
        n=read();kk=read();
        for (int i=1;i<=n;++i) a[i]=read();
        memset(dp,0,sizeof(dp));dp[0][0]=1;
        for (int i=1;i<=n;++i){
            int l,r;
            for (l=i;l>1&&a[l-1]<a[i];--l);
            for (r=i;r<n&&a[r+1]<a[i];++r);
            (dp[kk][i]+=dp[kk][i-1])%=P;
            for (int k=kk-1;k>=0;--k){
                dlt[l-1]=0;
                for (int j=l;j<=r;++j) dlt[j]=(dlt[j-1]+dp[k][j-1])%P;
                for (int j=l;j<=r;++j) (dp[k+1][j]+=dlt[j])%=P;
                (dp[k][i]+=dp[k][i-1])%=P;
                (dp[k+1][i]+=P-dp[k][i-1])%=P;
            }
        }
        int ans=0;
        for (int i=0;i<=kk;++i) (ans+=dp[i][n])%=P;
        printf("%d
    ",ans);
        return 0;
    }
    

      

  • 相关阅读:
    二分法检索数组
    Linux安装CDH
    myeclipse操作hdfs
    Linux安装hbase
    Linux安装zookeeper
    Linux安装msql
    fluem全分布环境搭建
    bash: jps: 未找到命令...
    自动化项目Jenkins持续集成
    linux卸载mysql====安装新的虚拟机 自带的基本都要卸载!? mysql tomcat java Python可以不用卸载
  • 原文地址:https://www.cnblogs.com/wangyurzee7/p/5554380.html
Copyright © 2011-2022 走看看