求序列完美度(trie+贪心)

Posted LittlePointer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求序列完美度(trie+贪心)相关的知识,希望对你有一定的参考价值。

题目链接:

求序列完美度

题目描述

给出由n个数组成的序列s,规定第i个数s[i]到第j个数s[j]组成的子序列的完美度为该子序列中所有数的和与任意一个不在该子序列中的数进行异或运算得到的值中的最大值,即perfect(s[i]~s[j])=max(sum(s[i]~s[j])^x),x为非子序列的数。现求完美度最大的子序列与它的完美度是多少

输入

第一行输入一个数T表示共有T组数据

输入一个数n表示序列有n个数

接下来有n个数,角标为1-n,表示序列的组成

1<=T<=100

3<=n<=1000

0<=s[i]<=1000000

输出

输出四个数:i,j,x,perfect[s[i]~s[j]],分别表示完美度最大的子序列的左端点(1<=i<=n),右端点(i<=j<=n),x(参见题目描述)和序列的完美度(如有多组子序列完美度相同,输出左端点靠前的,若左端点相同输出右端点靠前的)

样例输入

2
3
1 2 3
3
1 3 2

样例输出

2 3 1 4
1 2 2 6

题意:

思路:一个trie树,然后贪心就行,感觉题目描述有问题,还有数据范围有问题,看代码就知道了;

AC代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
int n,a[maxn];
struct node
{
    int l,r,x,mx;
}ans;
int ch[maxn*30][2],sz,val[maxn*30],vis[maxn*maxn];
void insert(int x)
{
    int u=0;
    for(int i=29;i>=0;i--)
    {
        int c=((x>>i)&1);
        if(!ch[u][c])
        {
            memset(ch[sz],0,sizeof(ch[sz]));
            val[sz]=0;
            ch[u][c]=sz++;
        }
        u=ch[u][c];
        val[u]++;
    }
}
inline void del(int x)
{
    int u=0;
    for(int i=29;i>=0;i--)
    {
        int c=((x>>i)&1);
        u=ch[u][c];
        val[u]--;
    }
}
int get_ans(int x)
{
    int u=0,tep=0;
    for(int i=29;i>=0;i--)
    {
        int c=(((x>>i)&1)^1);
        if(val[ch[u][c]])u=ch[u][c],tep|=(1<<i);
        else u=ch[u][c^1];
    }
    return tep;
}
inline void init()
{
    sz=1;memset(ch[0],0,sizeof(ch[0]));
    for(int i=1;i<=n;i++)insert(a[i]);
}
inline void solve(int p)
{
    init();
    int sum=0;
    for(int i=p;i<=n;i++)
    {
        del(a[i]);
        sum+=a[i];
        int g=get_ans(sum);
        if(g>ans.mx)ans.mx=g,ans.l=p,ans.r=i,ans.x=sum^g;
        else if(g==ans.mx)
        {
            if(p<ans.l)ans.l=p,ans.r=i,ans.x=sum^g;
            else if(p==ans.l&&i<ans.r)ans.r=i,ans.x=sum^g;
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        ans.mx=-1;
        for(int i=1;i<=n;i++)solve(i);
        printf("%d %d %d %d\n",ans.l,ans.r,ans.x,ans.mx);
    }
    return 0;
}

  

以上是关于求序列完美度(trie+贪心)的主要内容,如果未能解决你的问题,请参考以下文章

51nod贪心算法入门-----完美字符串

51Nod 1182 完美字符串 (贪心)

贪心基础入门讲解一——完美字符串

好题收集 异或最大值(贪心,trie树)

CF706DVasiliy's Multiset Trie+贪心

Neko and Aki's Prank CodeForces - 1152D (括号序列,dp)