• Palindrome Bo (预处理 + 区间DP)


    先进行离散化,然后再预处理出所有位置的下一个元素,做好这一步对时间的优化非常重要。

    剩下的就是一般的DP了。区间DP

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 5005;
    const ll mod = 1e9 + 7;
    
    ll dp[maxn][maxn], f[maxn][maxn], a[maxn];
    int nex[maxn][maxn], pre[maxn][maxn];
    pair<ll, int>discre[maxn];
    
    int main(){
        int n;while(~scanf("%d", &n)){
            for(int i = 1; i <= n; i ++){
                scanf("%lld", &a[i]);
                discre[i].first = a[i];
                discre[i].second = i;
            } sort(discre + 1, discre + 1 + n);
            discre[0].first = -1;
            int cnt = 0;
            for(int i = 1; i <= n; i ++){
                if(discre[i].first != discre[i - 1].first) cnt ++;
                a[discre[i].second] = cnt;
            }
            a[0] = a[n + 1] = cnt + 1;
            memset(dp, -1, sizeof(dp));
            memset(nex, 0, sizeof(nex));
            memset(pre, 0, sizeof(pre));
            for(int i = 0; i <= n + 1; i ++){
                for(int j = i + 1; j <= n + 1; j ++)
                    if(!nex[i][a[j]]) nex[i][a[j]] = j;
                for(int j = i - 1; j >= 0; j --)
                    if(!pre[i][a[j]]) pre[i][a[j]] = j;
            }
            for(int l = n + 1; l >= 0; l -- ){
                ll ans1 = 0, ans2 = 1;
                for(int r = l; r <= n + 1; r ++){
                    ll tmp1, tmp2;
                    if(l == r){
                        dp[l][r] = f[l][r] = 1;
                        continue;
                    }
    
                    if(a[r - 1] <= a[l]){
                        tmp1 = dp[nex[l][a[r-1]]][pre[r-1][a[r-1]]];
                        tmp2 =  f[nex[l][a[r-1]]][pre[r-1][a[r-1]]];
                        if(ans1 == tmp1) ans2 = (ans2 - tmp2 + mod) % mod;
                        if(ans1 < tmp1) ans1 = tmp1, ans2 = tmp2;
                        tmp1 = dp[nex[l][a[r-1]]][r - 1];
                        tmp2 =  f[nex[l][a[r-1]]][r - 1];
                        if(ans1 == tmp1) ans2 = (ans2 + tmp2) % mod;
                        if(ans1 < tmp1) ans1 = tmp1, ans2 = tmp2;
                    }
    
                    if(a[l] == a[r]){
                        dp[l][r] = ans1 + 2;
                        f[l][r] = ans2;
                    }else dp[l][r] = f[l][r] = 0;
                }
            }
            ll ans1 = 0, ans2 = 0;
            for(int i = 1; i <= cnt; i ++){
                if(dp[nex[0][i]][pre[n+1][i]] > ans1){
                    ans1 = dp[nex[0][i]][pre[n+1][i]];
                    ans2 =  f[nex[0][i]][pre[n+1][i]];
                }else if(ans1 == dp[nex[0][i]][pre[n+1][i]])
                    ans2 = (ans2 + f[nex[0][i]][pre[n+1][i]]) % mod;
            }
            printf("%lld %lld
    ",ans1, ans2);
        }
        return 0;
    }
    more crazy more get!
  • 相关阅读:
    响应式Web设计- 背景图片
    55、装饰器的写法以及应用场景。
    54、用尽量多的方法实现单例模式
    53、 什么是反射?以及应用场景?
    52、列举面向对象中的特殊成员以及应用场景
    51、静态方法和类方法区别?
    算法----练习题2
    50、如何判断是函数还是方法?
    49、是否使用过functools中的函数?其作用是什么?
    48、面向对象中super的作用?
  • 原文地址:https://www.cnblogs.com/wethura/p/9820368.html
Copyright © 2020-2023  润新知