• hihocoder #1609 : 数组分拆II(思维)


    题目链接:http://hihocoder.com/problemset/problem/1609

    题解:就先拿一个数组最多分成两部分来说吧

    8

    1 2 3 4 5 1 2 3

    显然 输出时2 3

    可以这样分(1 2 3( 4 5 )1 2 3)显然分要分在(^4^5^)“^”这3个地方也就是说如果设pre[i]表示i位置最前面能到哪个位置,dp[i]表示i这个位置最少能分成几组。

    那么ans[i]=Sum(ans[j] , (dp[j]=dp[i]-1 && j > pre[i]))那么就可以考虑前缀和。如果是单纯的求i的前缀没什么意义,可以考虑球sum[dp[i]]表示到i的位置长度为dp[i]

    的一共有几种分法。这样就可以方便求出Sum(ans[j] , (dp[j]=dp[i]-1 && j > pre[i]))

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #define mod 1000000007
    using namespace std;
    const int M = 1e5 + 10;
    typedef long long ll;
    int a[M] , pre[M] , dp[M];
    ll ans[M] , sum[M];
    bool vis[M];
    int main() {
        int n;
        scanf("%d" , &n);
        for(int i = 0 ; i < n ; i++) {
            scanf("%d" , &a[i]);
        }
        memset(pre , -1 , sizeof(pre));
        memset(dp , -1 , sizeof(dp));
        memset(vis , false , sizeof(vis));
        int left = -1;
        for(int i = 0 ; i < n ; i++) {
            if(vis[a[i]]) {
                left++;
                while(a[i] != a[left]) {
                    vis[a[left]] = false;
                    left++;
                }
            }
            pre[i] = left;
            vis[a[i]] = true;
        }
        for(int i = 0 ; i < n ; i++) {
            if(pre[i] == -1) {
                dp[i] = 1;
            }
            else {
                if(dp[i] == -1) dp[i] = dp[pre[i]] + 1;
                else dp[i] = min(dp[i] , dp[pre[i]] + 1);
            }
        }
        for(int i = 0 ; i < n ; i++) {
            if(pre[i] == -1) {
                ans[i] = 1;
                sum[dp[i]] += ans[i];
                sum[dp[i]] %= mod;
            }
            else {
                for(int j = max(0 , pre[i - 1]) ; j < pre[i] ; j++) {
                    sum[dp[j]] -= ans[j];
                    sum[dp[j]] %= mod;
                }
                ans[i] += sum[dp[i] - 1];
                sum[dp[i]] += ans[i];
                sum[dp[i]] %= mod;
            }
        }
        printf("%d %lld
    " , dp[n - 1] , (ans[n - 1] + mod) % mod);
        return 0;
    }
  • 相关阅读:
    简单的理解原型链
    react->Context笔记
    工作上git指令小结
    vue 绑定事件如何传递参数的同时拿到事件对象
    vsCode卸载后重新安装,以前的插件有没有效果的解决方法
    mongo 分组 aggregation
    Redisson分布式锁原理
    Virtual server server already has a web module live-mix-1.0.2-t230 loaded at / therefore web module
    二进制中 1 的个数
    替换空格
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/7677192.html
Copyright © 2020-2023  润新知