1. 程式人生 > >CodeForce-811C Vladik and Memorable Trip(動態規劃)

CodeForce-811C Vladik and Memorable Trip(動態規劃)

需要 都在 去重 dex long ner n) 數列 define

Vladik and Memorable Trip

CodeForces - 811C

有一個長度為 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(動態規劃)