codeforces 811C Vladik and Memorable Trip

来源:互联网 发布:原装ubuntu的电脑 编辑:程序博客网 时间:2024/05/18 22:40

题意:选择n个区间内所有的元素不能在外部出现,求所有各区间内的集合元素异或和?


思路:先预处理可行的区间,然后扫一波即可。


#include <iostream>#include <cstring>#include <cstdio>#include <map>#include <queue>#include <cmath>#include <algorithm>#include <set>using namespace std;#define LL long longconst 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;}

原创粉丝点击