题意:选择n个区间内所有的元素不能在外部出现,求所有各区间内的集合元素异或和?
思路:先预处理可行的区间,然后扫一波即可。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <map>
#include <queue>
#include <cmath>
#include <algorithm>
#include <set>
using namespace std;
#define LL long long
const int inf=0x7fffffff;
int n;
int a[5005];
int lf[5005];
int rf[5005];
int dp[5005][5005];
int ans[5005];
int v[5005];
int maxl[5005][16], minl[5005][16];
int min(int a, int b)
{
if (a>b) return b; return a;
}
int max(int a, int b)
{
if (a>b) return a; return b;
}
void S_table()
{
int l = int(log((double)n)/log(2.0));
for (int j=1;j<=l;j++)
{
for (int i=1; i + (1 << (j-1) ) - 1 <=n;++i)
{
maxl[i][j] = max(maxl[i][j-1], maxl[i + (1 << (j-1) )][j-1]);
minl[i][j] = min(minl[i][j-1], minl[i + (1 << (j-1) )][j-1]);
}
}
}
int min_getl(int l,int r)
{
int k = int(log((double)(r-l+1))/log(2.0));
int a2 = min(minl[l][k], minl[r - (1<<k) + 1][k]);
return a2;
}
int max_getr(int l,int r)
{
int k = int(log((double)(r-l+1))/log(2.0));
int a1 = max(maxl[l][k], maxl[r - (1<<k) + 1][k]);
return a1;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(lf[a[i]]==0)
lf[a[i]]=i;
rf[a[i]]=i;
}
for(int i=1;i<=n;i++)
{
minl[i][0] = lf[a[i]];
maxl[i][0] = rf[a[i]];
}
S_table();
for(int i=1;i<=n;i++)
{
int s=0;
memset(v,0,sizeof(v));
for(int j=i;j<=n;j++)
{
if(!v[a[j]])
{
v[a[j]]=1;
s^=a[j];
}
if(min_getl(i,j)==i&&max_getr(i,j)==j)
dp[i][j]=s;
}
}
for(int i=1;i<=n;i++)
{
ans[i]=ans[i-1];
for(int k=0;k<i;k++)
ans[i]=max(ans[i],dp[i-k][i]+ans[i-k-1]);
}
printf("%d\n",ans[n]);
return 0;
}