Wannafly挑战赛14 E 线性基

E 无效位置

题目描述

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

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

第二行读入n个正整数,第i个表示ai

第三行读入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

tags:
把删除转为添加,从后往前添加,每次可以用线性基快速算出异或最大值。因为还有要合并的情况,要确定祖先,所以要用个并查集维护一下。

//https://www.nowcoder.com/acm/contest/81/E
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 200005;

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;
    }
    bool is_in(long long val) { //存在性
        for(int i=60; i>=0; --i) {
            if(val&(1LL<<i)) {
                if(d[i]) 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() {  //求 k 小值前加
        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) { //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;
    }
} LB[N];
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;
}

int n, fa[N], cnt;
bool vis[N];
int Find(int x) { return fa[x]==x ? x : fa[x]=Find(fa[x]); }
void  Unite(int x, int y) {
    int fax = Find(x), fay = Find(y);
    fa[fax] = fay;
    LB[fay] = merge(LB[fax], LB[fay]);
}
ll  a[N], mx=0;
int x[N], id[N];
stack< ll > Stack;
ll ans = 0;
int main()
{
    rep(i,0,N-1) fa[i] = i;
    scanf("%d", &n);
    rep(i,1,n) scanf("%lld", &a[i]);
    rep(i,1,n) scanf("%d", &x[i]);
    per(i,n,1)
    {
        vis[x[i]] = true;
        LB[++cnt].Insert(a[x[i]]);
        id[x[i]] = cnt;
        if(vis[x[i]-1]) Unite(id[x[i]-1], id[x[i]]);
        if(vis[x[i]+1]) Unite(id[x[i]+1], id[x[i]]);
        ans = max(ans, LB[cnt].query_max());
        Stack.push(ans);
    }
    while(!Stack.empty())
        printf("%lld\n", Stack.top()), Stack.pop();

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/sbfhy/p/9019647.html