【Wannafly挑战赛21】 大水题 【DP】

链接:https://www.nowcoder.com/acm/contest/159/C
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
题目描述
现在给你N个正整数ai,每个数给出一“好数程度” gi(数值相同但位置不同的数之间可能有不同的好数程度)。对于在 i 位置的数,如果有一在j位置的数满足 j < i 且 ai=aj,则你可以将位于[i,j]闭区间内的序列评为“好序列”,然后获得∑gk(j≤k≤i)(此闭区间内“好数程度”之和)分数。
注意: 在所有情况下,每个数都只能被一个”好序列”包含(只能与其他相应数被评为”好序列”一次);在符合要求的情况下,”好序列”的评定次数不受限制,且通过不同”好序列”获得的分数可以累加。

输入描述:
第一行有一个正整数N。
接下来的一行有N个正整数ai,表示意义如上。
(保证ai在32位整型范围内)
接下来的一行有N个正整数gi,表示ai的”好数程度”。
(保证gi在64位整型范围内)
输出描述:
一个整数,你可以获得的最大分数(通过不同”好序列”获得的分数可以累加),保证答案在64位整型范围内。
示例1
输入
复制
7
1 2 1 2 3 2 3
1 4 3 4 3 4 5
输出
复制
23
备注:
数据范围 2≤N≤300000

分析: 因为每个点只可以用一次,所以我们可以用多开一个状态看是否取得第i个点,即 d p [ 0 ] [ i ] 表示 [ 1 i ]区间的不取 g [ i ] 的最大值, d p [ 1 ] [ i ] 表示 [ 1 i ] 区间的取 g [ i ] 的最大值.

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const int N = (int) 300000 + 11;
const int M = (int) 1e6 + 11;
const int MOD = (int)1e9 + 7;
const int INF =(int)0x3f3f3f3f;

#include <ext/rope>
using namespace __gnu_cxx;

ll a[N], g[N], dp[2][N]; //dp[0][i] 表示不取a[i]的最大值, dp[1][i] 表示取a[i]的最大值.
int main(){
    int n; scanf("%d" ,&n);
    for(int i = 1; i <= n; i++) scanf("%lld" , a + i);
    for(int i = 1; i <= n; i++){
        scanf("%lld", g + i);
        g[i] += g[i - 1];
    }
    memset(dp, 0, sizeof(dp));
    map<ll, int> last;
    for(int i = 1; i <= n; i++){
        dp[0][i] = max(dp[1][i - 1], dp[0][i - 1]);
        if(last[a[i]] != 0) {
            dp[1][i] = max(dp[1][i], dp[0][last[a[i]]] + g[i] - g[last[a[i]] - 1]);
            dp[1][i] = max(dp[1][i], dp[1][last[a[i]]] + g[i] - g[last[a[i]]]);
        }
        last[a[i]] = i;
    }
    printf("%lld\n", max(dp[0][n], dp[1][n]));
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37383726/article/details/81412773