zoukankan      html  css  js  c++  java
  • zoj3872 Beauty of Array (dp)

    题目链接:

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3872

    题意:

    给你n个数,求这n个数的连续子序列中不算重复的数的和,比如第二个样例他的子序列就是{2},{2,3},{2,3,3},{3},{3,3},{3};但每个子序列中重复的元素不被算入,所以他们的总和就是2+5+5+3+3+3=21;

    思路:

    考虑到当前第i个数,对答案的贡献是多少,dp[i]表示第i个数所做的贡献

    比如 1, 2, 3

    ----------------------------------

    1   dp[1] = 1;

    ----------------------------------

    2

    1,2   dp[i] = dp[i-1]+a[i]*i = 1 + 2*2

    ----------------------------------

    3

    2,3

    12,3  dp[i] = dp[i-1]+a[i]*i = 5 + 3*3   红色部分是dp[i-1],  对于第i个数的贡献,只是把第i-1个数的贡献,加上当前第i个数出现了几次(i)

    -----------------------------------

    例如有序列1,2,3,4,5

    若在末尾加入一个序列中没有的数N,则新产生的子序列为:

    N;

    5,N;

    4,5,N;

    3,4,5,N;

    2,3,4,5,N;

    1,2,3,4,5,N;

    则增加的输出值为:

    5;

    4,5;

    3,4,5;

    2,3,4,5;

    1,2,3,4,5;

    的输出值(dp[5])+6*N;

    若在末尾加入一个序列中出现过的数字3,则新产生的子序列为:

    3;

    5,3;

    4,5,3;

    3,4,5,3

    2,3,4,5,3

    1,2,3,4,5,3

    0,1,2,3,4,5,3

    其中,最后四个子序列,因为末尾的3是第二次出现,故输出值里不将其计入,因此有效的子序列只有前面3个; dp[7] = dp[6]+7*a[7]-vis[a[7]]*a[7];  vis[a[i]]表示a[i]这个数最后出现的位置。

    最终答案就是所有dp值加起来

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define MS(a) memset(a,0,sizeof(a))
    #define MP make_pair
    #define PB push_back
    const int INF = 0x3f3f3f3f;
    const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
    inline ll read(){
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    //////////////////////////////////////////////////////////////////////////
    const int maxn = 1e5+10;
    
    int T;
    int vis[maxn*10];
    ll dp[maxn],a[maxn];
    
    int main(){
        cin >> T;
        while(T--){
            MS(vis); MS(dp);
            int n = read();
            for(int i=1; i<=n; i++)
                a[i] = read();
            ll ans = 0;
            for(int i=1; i<=n; i++){
                dp[i] = dp[i-1] + (i-vis[a[i]])*a[i];
                vis[a[i]] = i;
                ans += dp[i];
            }
            cout << ans << endl;
        }
    
        return 0;
    }
  • 相关阅读:
    Linux 02
    Linux 01
    React 函数式组件的 Ref 和子组件访问(useImperativeHandle)
    排序算法之 Java插入排序算法
    排序算法之 Java选择排序算法
    排序算法之 Java冒泡算法
    类加载的过程---验证和准备
    类加载的过程---加载
    mysql explain 查询处理的结果详解
    springboot整合分布式缓存hazelCast
  • 原文地址:https://www.cnblogs.com/yxg123123/p/7257383.html
Copyright © 2011-2022 走看看