[分治][线性基]BZOJ 4184: shallot

来源:互联网 发布:美萍软件怎么样 编辑:程序博客网 时间:2024/06/05 12:00

Description

小苗去市场上买了一捆小葱苗,她突然一时兴起,于是她在每颗小葱苗上写上一个数字,然后把小葱叫过来玩游戏。
每个时刻她会给小葱一颗小葱苗或者是从小葱手里拿走一颗小葱苗,并且让小葱从自己手中的小葱苗里选出一些小葱苗使得选出的小葱苗上的数字的异或和最大。

Solution

挺显然的分治+线性基的吧
用线段树里定位区间的方法,把每个操作存在的区间定位好。
最后线性基询问就好啦。

#include <bits/stdc++.h>using namespace std;const int N = 505050;inline char get(void) {    static char buf[100000], *S = buf, *T = buf;    if (S == T) {        T = (S = buf) + fread(buf, 1, 100000, stdin);        if (S == T) return EOF;    }    return *S++;}template<typename T>inline void read(T &x) {    static char c; x = 0; int sgn = 0;    for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1;    for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';    if (sgn) x = -x;}struct LB {    int a[32];    inline void Clear(void) {        for(int i = 0; i < 31; i++) a[i] = 0;    }    inline void Insert(int x) {        for (int i = 31; i >= 0; i--)            if ((x >> i) & 1) {                if (!a[i]) {                    a[i] = x; break;                }                x ^= a[i];            }    }    inline int Max(void) {        int res = 0;        for (int i = 31; i >= 0; i--)            if ((a[i] ^ res) > res) res ^= a[i];        return res;    }};map<int, int> mp;int cnt[N], lst[N], val[N];struct data {    int l, r, x;    data(int _l = 0, int _r = 0, int _x = 0):l(_l), r(_r), x(_x) {}};LB I;vector<data> a;int n, m, x, Mcnt, pos, sgn;int ans[N];inline void DivAndConq(int l, int r, LB L, vector<data> arr) {    vector<data> ls, rs;    ls.clear(); rs.clear();    int mid = (l + r) >> 1;    for (int i = 0; i < arr.size(); i++)        if (arr[i].l <= l && arr[i].r >= r) L.Insert(val[arr[i].x]);        else {            if (arr[i].l <= mid) ls.push_back(arr[i]);            if (arr[i].r > mid) rs.push_back(arr[i]);        }    if (l == r) return (void)(ans[l] = L.Max());    DivAndConq(l, mid, L, ls);    DivAndConq(mid + 1, r, L, rs);}int main(void) {    freopen("1.in", "r", stdin);    read(n);    for (int i = 1; i <= n; i++) {        read(x); sgn = x > 0 ? 1 : -1;        if (sgn < 0) x = -x;        if (!mp.count(x)) {            mp[x] = ++Mcnt;            val[Mcnt] = x;        }        pos = mp[x];        if (!cnt[pos]) {            a.push_back(data(i, n, pos));            lst[pos] = a.size() - 1;        }        cnt[pos] += sgn;        if (!cnt[pos]) a[lst[pos]].r = i - 1;    }    I.Clear();    DivAndConq(1, n, I, a);    for (int i = 1; i <= n; i++)        printf("%d\n", ans[i]);    return 0;}
原创粉丝点击