• 牛客网 Wannafly挑战赛14 E.无效位置 (并查集+线性基)


    链接:https://www.nowcoder.com/acm/contest/81/E
    来源:牛客网

    题目描述

    给一个1-base数组{a},有N次操作,每次操作会使一个位置无效。一个区间的权值定义为这个区间里选出一些数的异或和的最大值。求在每次操作前,所有不包含无效位置的区间的权值的最大值。
    输入描述:

    第一行读入一个正整数(1 <= n <= 105)

    第二行读入n个正整数,第i个表示a[i](0<= a[i] <= 109)

    第三行读入n个正整数,第i个表示x[i]即第i次操作的位置,保证x[i]互不相同。

    输出描述:

    输出n行答案

    示例1
    输入

    10
    169 816 709 896 58 490 97 254 99 796
    4 2 3 10 5 6 1 8 9 7

    输出

    1023
    994
    994
    994
    490
    490
    254
    254
    99
    97

    分析:

    根据题目能够想到线性基,又因为正向删去不好处理,可以离线反向进行插入。

    在每次插入后,答案可能保留原先的最大值,或者插入的位置构成新的最大值。

    然后需要讨论的是插入的位置,是否与左右构成新的区间,如果当前插入位置为x,那么需要看x+1上是否存在值,如果有值,需要进行线性基的合并。以该区间最左边的位置作为合并后的线性基。可用并查集来维护这个位置。然后在看x-1位置上是否有值,如果有,用相同的方式进行线性基的合并。

    最后输出得到的线性基的最大值。

    代码如下:

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #include <iostream>
    #include <vector>
    #include <stack>
    #include <cstring>
    using namespace std;
    const int MAXN=1e5+100;
    typedef long long LL ;
    int pre[MAXN];
    int vis[MAXN];
    LL  a[MAXN];
    
    int Find(int x)
    {
        int h,tmp;
        h=x;
       while(x!=pre[x])
         x=pre[x];
       while(x!=h)
       {
          tmp=pre[h];
          pre[h]=x;
          h=tmp;
       }
       return x;
    }
    
    void join(int x,int y)
    {
        int p=Find(x);
        int q=Find(y);
        if(p<q)
        pre[q]=p;
        else if(p>q)
        pre[p]=q;
    }
    struct node
    {
        LL  id;
        LL  x;
        LL  ans;
    }qes[MAXN];
    struct L_B{
        long long d[61],p[61];
        int cnt;
        L_B()
        {
            cnt=0;
        }
        bool insert(long long val)
        {
            for (int i=60;i>=0;i--)
                if (val&(1LL<<i))
                {
                    if (!d[i])
                    {
                        d[i]=val;
                        break;
                    }
                    val^=d[i];
                }
            return val>0;
        }
        long long query_max()
        {
            long long ret=0;
            for (int i=60;i>=0;i--)
                if ((ret^d[i])>ret)
                    ret^=d[i];
            return ret;
        }
        long long query_min()
        {
            for (int i=0;i<=60;i++)
                if (d[i])
                    return d[i];
            return 0;
        }
        void rebuild()
        {
            for (int i=60;i>=0;i--)
                for (int j=i-1;j>=0;j--)
                    if (d[i]&(1LL<<j))
                        d[i]^=d[j];
            for (int i=0;i<=60;i++)
                if (d[i])
                    p[cnt++]=d[i];
        }
        long long kthquery(long long k)
        {
            long long ret=0;
            if (k>=(1LL<<cnt))
                return -1;
            for (int i=60;i>=0;i--)
                if (k&(1LL<<i))
                    ret^=p[i];
            return ret;
        }
    };
    L_B merge(const L_B &n1,const L_B &n2)
    {
        L_B ret=n1;
        for (int i=60;i>=0;i--)
            if (n2.d[i])
                ret.insert(n2.d[i]);
        return ret;
    }
    LL  n;
    L_B A[MAXN];
    int main()
    {
    
         LL ans=0;
         scanf("%lld",&n);
         for(int i=1;i<=n;i++)
         {
          pre[i]=i;
         scanf("%lld",&a[i]);
         }
         for(int i=1;i<=n;i++)
         {
            qes[i].id=i;
            scanf("%lld",&qes[i].x);
         }
    
        for(int i=n;i>=1;i--)
         {
            A[qes[i].x].insert(a[qes[i].x]);
            vis[qes[i].x]=1;
            if(vis[qes[i].x+1])
            {
             A[Find(qes[i].x)]=merge(A[Find(qes[i].x)],A[Find(qes[i].x+1)]);
             join(qes[i].x,qes[i].x+1);
            }
             if(vis[qes[i].x-1])
            {
             A[Find(qes[i].x-1)]=merge(A[Find(qes[i].x-1)],A[Find(qes[i].x)]);
             join(qes[i].x,qes[i].x-1);
            }
            ans=max(ans,A[Find(qes[i].x)].query_max());
            qes[i].ans=ans;
         }
         for(int i=1;i<=n;i++)
        cout<<qes[i].ans<<endl;
        return 0;
    }
  • 相关阅读:
    PHP面试题遇到的几个坑。...面壁ing
    Java基础- super 和 this 解析
    openStack use
    ceph伦理概念
    openstack core components use 总结
    current imporant Posts
    openNebula rgister img instance vms error collections
    openStack images概念及维护
    Error copying image in the datastore: Not allowed to copy image file
    OpenNebula openldap集成
  • 原文地址:https://www.cnblogs.com/a249189046/p/8953782.html
Copyright © 2020-2023  润新知