• [HEOI2013]ALO


    题目描述:

    现在你拥有 n 颗宝石,每颗宝石有一个能量密度,记为 ai,这些宝石的能量 密度两两不同。现在你可以选取连续的一些宝石(必须多于一个)进行融合,设 为 ai, ai+1, …, aj,则融合而成的宝石的能量密度为这些宝石中能量密度的次大值 与其他任意一颗宝石的能量密度按位异或的值,即,设该段宝石能量密度次大值 为 k,则生成的宝石的能量密度为 max{k xor ap | ap ≠ k , i ≤ p ≤ j}

    题解:
    首先建可持久化Trie。

    然后是区间的选取问题。

    想了好久想出来一种方法:

    对于每个点建双向链表,从小到大删点。

    对于每个点可取区间为[左方第二个比它大的+1,右方第二个比它大的-1]。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 50050
    inline int rd()
    {
        int f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
        return f*c;
    }
    int n,a[N];
    struct Trie
    {
        int tot,siz[32*N],ch[32*N][2],rt[N];
        void insert(int k,int x)
        {
            int u,l=rt[k-1];
            rt[k]=u=++tot;
            for(int i=30;i>=0;i--)
            {
                ch[u][0]=ch[l][0],ch[u][1]=ch[l][1],siz[u]=siz[l]+1;
                int k = (x>>i)&1;
                ch[u][k]=++tot;
                u=ch[u][k],l=ch[l][k];
            }
            siz[u]=siz[l]+1;
        }
        int query(int l,int r,int x)
        {
            l = rt[l],r = rt[r];
            int ret = 0;
            for(int i=30;i>=0;i--)
            {
                int k = (x>>i)&1;
                if(siz[ch[r][!k]]-siz[ch[l][!k]])
                {
                    l=ch[l][!k],r=ch[r][!k];
                    ret|=(1<<i);
                }else l=ch[l][k],r=ch[r][k];
            }
            return ret;
        }
    }tr;
    int l[N],r[N],lf[N],rg[N];
    struct node
    {
        int x,v;
    }p[N];
    bool cmp(node a,node b)
    {
        return a.v<b.v;
    }
    int main()
    {
        n=rd();
        for(int i=1;i<=n;i++)
        {
            a[i]=rd(),l[i]=i-1,r[i]=i+1;
            tr.insert(i,a[i]);
            p[i].x=i,p[i].v=a[i];
        }
        l[0]=0,r[0]=1;
        l[n+1]=n,r[n+1]=n+1;
        int ans = 0;
        sort(p+1,p+1+n,cmp);
        for(int i=1;i<=n;i++)
        {
            int u = p[i].x;
            r[l[u]]=r[u],l[r[u]]=l[u];
            lf[u]=l[l[u]],rg[u]=r[r[u]];
        }
        for(int i=1;i<=n;i++)
            ans=max(ans,tr.query(lf[i],rg[i]-1,a[i]));
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    c语言分支和循环语句
    C语言基础知识
    磁盘管理-fdisk
    搭建Discuz
    KVM创建虚拟机相关操作
    WINRAR exe 捆绑 小游戏
    linux vi编辑器&文件目录管理
    灰鸽子木马的功能体验
    sqlalchemy 级联删除
    sqlalchemy 多对多
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10024032.html
Copyright © 2020-2023  润新知