题目描述
输入格式
输出格式
样例
数据范围与提示
对于 100%100\%100% 的数据,1≤n≤106,1≤k≤106,1≤vi≤1091leq nleq 10^6,1leq kleq 10^6,1leq v_ileq 10^91≤n≤10
6,1≤k≤106,1≤vi≤109。
题意 :类似于“拉火车”游戏,不过不太一样的是当出现相同的情况后你可以选择拉或者不拉,
思路分析 : 一看就是个 dp ,
dp[i] = dp[i-1]
dp[i] = max(dp[i], dp[j-1]+sum[i]-sum[j-1]) , i 与 j 为花色相同的地方
第一次写的时候就类似纯暴力的了,每次转移的时候从前面所有相同的地方转移,用 vector 存的,超时.... 后面发现 转移方程中的式子是可以优化的,每次找 dp[j-1]-sum[j-1]中最大的转移即可
代码示例 :
#define ll long long const ll maxn = 1e6+5; ll n, k; ll c[maxn], v[maxn]; ll sum[maxn], dp[maxn]; ll color[maxn]; void solve() { memset(color, 0x8f, sizeof(color)); for(ll i = 1; i <= n; i++){ dp[i] = dp[i-1]; dp[i] = max(dp[i], sum[i]+color[c[i]]); color[c[i]] = max(color[c[i]], dp[i-1]-sum[i-1]); } printf("%lld ", dp[n]); } int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); cin >> n >> k; for(ll i = 1; i <= n; i++) { scanf("%lld", &c[i]); } for(ll i = 1; i <= n; i++) { scanf("%lld", &v[i]); sum[i] = sum[i-1]+v[i]; } solve(); return 0; }