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
  • 相关阅读:
    [原创]存储过程,insert,case when then,处理性别问题 Virus
    [原创]c#,数据结构,栈 Virus
    [原创]软件自动化测试和.NET中的反射 Virus
    [原创]反射,.NET,委托 Virus
    《博客园精华集--NET3.x分册》第三轮结果
    (翻译)《Expert .NET 2.0 IL Assembler》 详要目录 更新到第8章
    MSIL翻译中的问题贴
    (翻译)《Expert .NET 2.0 IL Assembler》 第一章 简单示例 1.2 简单示例(二)
    (翻译)《Expert .NET 2.0 IL Assembler》 第一章 简单示例 1.2 简单示例(一)
    第三轮进度汇总
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/10244307.html
Copyright © 2011-2022 走看看