bzoj 4184 Shallot

有一个一开始为空的集合,每次加入一个数或者删除一个数,每次查询这个集合选出若干个数异或起来的最大结果

$n \leq 100000$

sol:

学了一波线性基

大概就是

1.插入一个数(其中 v 的大小是 logn)

void add(int x)
{
    for(int i=0;i<v.size();i++) if(x > (x ^ v[i]))x ^= v[i];
    if(x)
    {
        v.push_back(x);
        for(int i=v.size()-1;i;i--) if(v[i] > v[i - 1])swap(v[i],v[i - 1]);
    }
}

2.查询当前集合最大异或和

int cal()
{
    int ret = 0;
    for(int i=0;i<v.size();i++) if(ret < (ret ^ v[i])) ret ^= v[i];
    return ret;
}

其余的操作就没有了,合并的话是启发式合并,删除不资瓷,v 的大小就是当前极大线性无关集的大小

 

这道题一眼线段树分治,然后线性基裸题

#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline int read()
{
    int x = 0,f = 1;char ch = getchar();
    for(;!isdigit(ch);ch = getchar())if(ch == '-') f = -f;
    for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
    return x * f;
}
const int maxn = 500010;
int n,a[maxn],last[maxn];
map<int,int> hsh;
#define ls (x << 1)
#define rs ((x << 1) | 1)
struct Base
{
    vector<int> v;
    void add(int x)
    {
        for(int i=0;i<v.size();i++) if(x > (x ^ v[i]))x ^= v[i];
        if(x)
        {
            v.push_back(x);
            for(int i=v.size()-1;i;i--) if(v[i] > v[i - 1])swap(v[i],v[i - 1]);
        }
    }
    int cal()
    {
        int ret = 0;
        for(int i=0;i<v.size();i++) if(ret < (ret ^ v[i])) ret ^= v[i];
        return ret;
    }
};
Base seg[maxn << 2],cur;
inline void Insert(int x,int l,int r,int L,int R,int v)
{
    //cout<<x<<endl;
    if(L <= l && r <= R)
    {
        seg[x].add(v);
        return;
    }
    int mid = (l + r) >> 1;
    if(L <= mid)Insert(ls,l,mid,L,R,v);
    if(R > mid)Insert(rs,mid + 1,r,L,R,v);
}
inline void solve(int x,int l,int r,Base cur)
{
    for(int i=0;i<seg[x].v.size();i++)cur.add(seg[x].v[i]);
    if(l == r)
    {
        printf("%d\n",cur.cal());
        return;
    }
    int mid = (l + r) >> 1;
    solve(ls,l,mid,cur);solve(rs,mid + 1,r,cur);
}
int main()
{
    //freopen("20.in","r",stdin);
    n = read();
    for(int i=1;i<=n;i++)
    {
        a[i] = read();
        if(a[i] < 0)last[hsh[-a[i]]] = i - 1;
        else hsh[a[i]] = i;
    }
    for(int i=1;i<=n;i++)
    {
        if(a[i] < 0)continue;
        if(last[i] == 0)last[i] = n;
        Insert(1,1,n,i,last[i],a[i]);
    }
    solve(1,1,n,cur);
}
View Code

 

posted @ 2019-01-09 14:45  探险家Mr.H  阅读(161)  评论(0编辑  收藏  举报