Codeforces Round #416 (Div. 2) C

来源:互联网 发布:178软件源地址 编辑:程序博客网 时间:2024/06/03 22:07

这里写图片描述

题意:

有n个数字排列一行,现在让你选出几个段求出每一个段的异或然后相加,输出最大的
和。但是有一个条件是选出的段中如果有一个数字那么这个段需要包括所有的出现这
个数字的位置。

思路:

谁会想到这是dp呢?dp[i] 表示1~i之中所有分段的情况最大值,如果在1小于j小于等
于i的时候出现了符合题意的情况就保留最大值。

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = 5005;int n,a[maxn];int dp[maxn];int s[maxn],e[maxn],vis[maxn];int main(){    //freopen("in.txt","r",stdin);    scanf("%d",&n);    for(int i = 1;i <= n; i++) {        scanf("%d",&a[i]);        if(!s[a[i]])            s[a[i]] = i;        e[a[i]] = i;    }    for(int i = 1;i <= n; i++) {        dp[i] = dp[i-1];        memset(vis,0,sizeof(vis));        int ans = 0;        int Min = s[a[i]];        for(int j = i;j >= 1; j--) {            if(e[a[j]] > i) break;            if(!vis[a[j]]) {                ans ^= a[j];                vis[a[j]] = true;            }            Min = min(Min,s[a[j]]);            if(Min >= j)                dp[i] = max(dp[i],dp[j-1]+ans);        }    }    printf("%d\n",dp[n]);    return 0;}