zoukankan      html  css  js  c++  java
  • Luogu[P1108] 低价购买

    (Link)

    (mathcal{color{red}{Description}})

    请你求出一个数列的最长下降子序列长度,并为此求出其方案数。

    [1 leq N leq 5000 ]

    (mathcal{color{red}{Solution}})

    乍一看这个复杂度其实是卡死的……如果是(n^2)的话,我们的处理规模达到了(25,000,000),时限一秒的话……会感到很紧迫(qwq),但是的确能跑出来。

    我们下来思索,对于最朴素的算法,如果不求方案数的话,是要用(dp[i])表示到第(i)位的最长下降子序列长度,我们的纸张算法长这样:

    for(i = 1; i <= N; i ++)
    	for(j = 1; j <= N; j ++){
    		if (base[i] < base[j]) dp[i] = max(dp[i], dp[j] + 1), ans = max(dp[i], ans);
    	}
    

    那么,这样的话,对于第二问,我们就可以比较容易地求出方案数,做法是我们对第一问的DP数组再DP一次,就像这样:

    for(i = 1; i <= N; i ++){
    	if(dp[i] == 1) f[i] = 1 ;
    	for(j = 1; j <= N: j ++)
    		if(base[i] < base[j] && dp[j] == dp[i] - 1) f[i] += f[j] ;
    		else if(base[i] == base[j] && dp[j] == dp[i]) f[i] = 0 ;
    	if(f[i] == ans) res ++ ;
    	}
    

    嗯,这个应该挺好想的,本蒟唯一想错了的一点是,当时第二层循环里的else后面不应该是--应该是直接置为0才对qwq。

    嗯,然后呢这就是(n^2)做法。但我一开始写的是(nlogn)做法,但是发现(nlogn)的话,第二问就不能在第一问的基础上dp了……真是件扫兴的事啊QAQ。

    存一波代码(qwq)

        #include <cstdio>
        #include <iostream>
        #define MAXN 10010
    
        using namespace std ;
        int l, r, mid, i, j, ans ;
        int Len = 1, N, base[MAXN], f[MAXN], dp[MAXN] ;
    
        inline int qr(){
            int k = 0 ; char c = getchar() ;
            while(!isdigit(c)) c = getchar() ;
            while(isdigit(c)) k = (k << 1) + (k << 3) + c - 48, c = getchar();
            return k ;
        }
        int main() {
            N = qr( ) ;
            for(i = 1; i <= N; i ++){base[i] = qr( ); f[i] = 1 ;}
            for(i = 1; i <= N; i ++)
            	for(j = 1; j < i; j ++){
            		if(base[j] > base[i] && f[i] < f[j] + 1){
            			f[i] = f[j] + 1 ;
            			Len = max(Len, f[i]) ;
            		}
            	}
            cout << Len << " " ;
            for(i = 1; i <= N; i ++){
                if(f[i] == 1) dp[i] = 1 ;
                for(j = 1 ;j < i; j ++){
                    if(f[i] == f[j] + 1 && base[i] < base[j]) dp[i] += dp[j] ;
                    if(f[i] == f[j] && base[i] == base[j]) dp[i] = 0 ;
                }
                if(f[i] == Len) ans += dp[i] ;
            }
            cout << ans ;
            return 0 ;
        }
    

    (Xcode)写出来的……画风诡异(emmm)

  • 相关阅读:
    Spring:(八) mybatis-spring整合
    Spring:(七) Aop
    spring boot中@ControllerAdvice的用法
    spring boot中注册拦截器
    spring boot 中通过CORS实现跨域
    spring boot 中的路径映射
    浅析java中的string
    java并发编程如何预防死锁
    Redis集群增加节点和删除节点
    Redis删除集群以及重新启动集群
  • 原文地址:https://www.cnblogs.com/pks-t/p/9315189.html
Copyright © 2011-2022 走看看