zoukankan      html  css  js  c++  java
  • 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
    ",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
  • 相关阅读:
    可扩展多线程异步Socket服务器框架EMTASS 2.0
    认识迅雷界面引擎
    C语言 二维数组(指针)动态分配和释放(转)
    二维数组与双重指针(转)
    VC++6 调用teststand api的方法
    [VC6] 小谈如何解决VC6.0 open崩溃的问题(已解决)(转)
    Linux下C与Mysql的混合编程(转)
    VS2010生成安装包制作步骤 (转)
    SAO总结
    JS OOP编程
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/10244307.html
Copyright © 2011-2022 走看看