无效位置 (线性基合并)

链接: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
思路:
离线做 然后用并查集维护下,在合并下线性基就行了
accode

#include<bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e5+5;
int fa[maxn];
int n;
LL a[maxn];
int vis[maxn];
struct L_B{
    long long d[61],p[61];
    int cnt;
    L_B()
    {
        memset(d,0,sizeof(d));
        memset(p,0,sizeof(p));
        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)
    {
        int 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[maxn];
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]);
  //  cout<<ret.query_max()<<endl;
    return ret;
}
int the_find(int x)
{
    return x==fa[x]?x:fa[x] = the_find(fa[x]);
}
struct node
{
    int id;
    int p;
}Q[maxn];
int ans2[maxn];
int main()
{
    scanf("%d",&n);
    for(int i = 1;i<=n;i++){
        fa[i] = i;
    }
    memset(vis,0,sizeof(vis));
    for(int i = 1;i<=n;i++){
        scanf("%lld",&a[i]);
        L[0].insert(a[i]);
    }
   // cout<<L[0].query_max()<<endl;
    for(int i = 0;i<n;i++){
        scanf("%d",&Q[i].p);
        Q[i].id = i;
    }
    LL ans = 0;
    for(int i = n-1;i>=0;i--){
        vis[Q[i].p] = 1;
        L[Q[i].p].insert(a[Q[i].p]);
        if(Q[i].p>1){
            if(vis[Q[i].p-1]){
                int v = the_find(Q[i].p-1);
                fa[Q[i].p] = v;
               L[v] = merge(L[v],L[Q[i].p]);
            }
        }
        if(Q[i].p<n){
            if(vis[Q[i].p+1]){
                int v = the_find(Q[i].p+1);

                L[v] = merge(L[v],L[the_find(Q[i].p)]);
                 fa[the_find(Q[i].p)] = v;
            }
        }
       /* for(int i = 1;i<=n;i++){
            cout<<L[the_find(i)].query_max()<<' ';
        }
        cout<<endl;
        for(int i = 1;i<=n;i++){
            cout<<i<<' '<<the_find(i)<<endl;
        }*/
        ans = max(ans,L[the_find(Q[i].p)].query_max());
        ans2[Q[i].id] = ans;
    }
    for(int i = 0;i<n;i++){
        printf("%d\n",ans2[i]);
    }
}

猜你喜欢

转载自blog.csdn.net/w571523631/article/details/80372880