$dp$。
记录$dp[i]$表示以位置$i$为结尾的最大值。
枚举最后一段是哪一段,假设为$[j,i]$,那么可以用$max(dp[1]...dp[j-1]) + val[j][i]$去更新$dp[i]$。
判断区间是否合法可以记录选择每个位置必须需要取到的最小位置和最大位置,判断区间合法性的时候就只需判断区间内每一个数字的最小位置和最大位置是否均在该区间内。
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <map> #include <set> #include <cmath> using namespace std; int mx[5050],dp[5050],a[5050]; bool f[5050]; int L[5050],R[5050]; int n; int ll,rr; bool ok(int x,int y) { if(ll>=x&&ll<=y&&rr>=x&&rr<=y) return 1; return 0; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); if(L[a[i]]==0) L[a[i]] = i, R[a[i]] = i; R[a[i]] = i; } for(int i=1;i<=n;i++) { int vji = 0; ll = n+1, rr = 0; memset(f,0,sizeof f); for(int j=i;j>=1;j--) { if(f[a[j]]) {} else f[a[j]] = 1, vji = vji ^ a[j]; ll = min(ll,L[a[j]]); rr = max(rr,R[a[j]]); if(ok(j,i)) dp[i] = max(dp[i],mx[j-1] + vji); } mx[i] = max(mx[i-1],dp[i]); } printf("%d ",mx[n]); return 0; }