CodeForce-811C Vladik and Memorable Trip(动态规划)
Posted Ying_zx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForce-811C Vladik and Memorable Trip(动态规划)相关的知识,希望对你有一定的参考价值。
Vladik and Memorable Trip
有一个长度为 n 的数列,其中第 i 项为 ai。
现在需要你从这个数列中选出一些互不相交的区间,并且保证整个数列中所有相同的数都在同一个区间中或都不在任意一个区间中。
要求最大化每个区间所有数去重后的异或和的总和。输出这个总和。
预处理出每个数字第一个出现的位置和最后一个出现的位置。以及每个区间内不同数字的异或和。
dp[i]表示考虑到前i个人,最大值是多少。分情况讨论一下即可。
#include <cstdio> #include <iostream> #include <cmath> #include <algorithm> #include <string> #include <cstring> using namespace std; #define _ ios::sync_with_stdio(false) const int MAXN = 5010; const int INF = 0xfffffff; typedef long long ll; int n; ll a[MAXN]; int l[MAXN], r[MAXN]; ll s[MAXN][MAXN]; int vis[MAXN]; ll dp[MAXN]; int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%I64d", a + i); if (l[a[i]]) l[a[i]] = min(l[a[i]], i); else l[a[i]] = i; if (r[a[i]]) r[a[i]] = max(r[a[i]], i); else r[a[i]] = i; } for (int i = 1; i <= n; i++) { memset(vis, 0, sizeof(vis)); s[i][i] = a[i]; vis[a[i]] = 1; for (int j = i + 1; j <= n; j++) { if (!vis[a[j]]) { s[i][j] = s[i][j - 1] ^ a[j]; vis[a[j]] = 1; } else { s[i][j] = s[i][j - 1]; } } } dp[0] = 0; for (int i = 1; i <= n; i++) { int temp = a[i]; if (i == r[temp]) { int L = l[temp]; int ok = 1; for (int j = l[temp] + 1; j < r[temp]; j++) { if (r[a[j]] > i) { ok = 0; break; } L = min(l[a[j]], L); } if (ok) dp[i] = max(dp[i - 1], dp[L - 1] + s[L][i]); else dp[i] = dp[i - 1]; } else dp[i] = dp[i - 1]; } printf("%I64d\n", dp[n]); }
以上是关于CodeForce-811C Vladik and Memorable Trip(动态规划)的主要内容,如果未能解决你的问题,请参考以下文章
CodeForces 743C Vladik and fractions (数论)
CodeForces 743A Vladik and flights (水题)
Codeforces Round #416 (Div. 2) 811D Vladik and Favorite Game
(线段树+并查集) Codeforces Round #416 (Div. 2) E Vladik and Entertaining Flags