[BZOJ 4184] shallot 以时间为基底建线段树

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ 4184] shallot 以时间为基底建线段树相关的知识,希望对你有一定的参考价值。

题意

  给定时长 $n$ , 每个时刻有某个元素出现或者消失, 求每个时刻所有元素的最大异或值. 

  $n \le 500000$ .

 

分析

  通过 map 或者 hash , 我们可以知道 $O(n)$ 个 "一个元素 $x$ 在 $[l, r]$ " 出现的信息.

  对时间建立线段树, 每个节点开一个 vector , 对区间 $[l, r]$ 对应的所有节点插入一个 $x$ .

  对线段树进行 DFS , 同时动态维护线性基.

 

实现

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#include <map>
using namespace std;

#define F(i, a, b) for (register int i = (a); i <= (b); i++)
#define P(i, a, b) for (register int i = (a); i >= (b); i--)

const int N = 1500000;
const int E = 10000005;

int n; map<int, int> vis;
int M, tot, hd[N], nx[E], v[E];
int s[N], top, b[35];

inline int rd(void) {
    int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == -) f = -1;
    int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-0; return x*f;
}

inline void Ins(int x, int w) { nx[++tot] = hd[x], hd[x] = tot, v[tot] = w; }
inline void Fill(int L, int R, int w) {
    for (L--, R++, L += M, R += M; L^R^1; L >>= 1, R >>= 1) {
        if (!(L&1)) Ins(L^1, w);
        if (R&1) Ins(R^1, w);
    }
}

inline void Insert(int w) {
    P(i, 30, 0) if (w>>i&1)
        if (!b[i]) { b[s[++top] = i] = w; break; } else w ^= b[i];
}
inline int Max(void) { int res = 0; P(i, 30, 0) res = max(res, res ^ b[i]); return res; }
void Tsunami(int x, int L, int R) {
    if (R < 1 || L > n) return;
    
    int t = top;
    for (int k = hd[x]; k > 0; k = nx[k])
        Insert(v[k]);
    
    if (L == R)
        printf("%d\n", Max());
    else {
        int M = (L+R)>>1;
        Tsunami(x<<1, L, M);
        Tsunami(x<<1|1, M+1, R);
    }
    
    for (; top > t; s[top--] = 0)
        b[s[top]] = 0;
}

int main(void) {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4184.in", "r", stdin);
        freopen("bzoj4184.out", "w", stdout);
    #endif
    
    n = rd(); for (M = 1; M < n+2; M <<= 1);
    F(i, 1, n) {
        int x = rd();
        if (x > 0) vis[x] = i; else x = -x, Fill(vis[x], i-1, x), vis[x] = 0;
    }
    for (map<int, int>::iterator it = vis.begin(); it != vis.end(); it++)
        if (it -> second > 0)
            Fill(it -> second, n, it -> first);
    
    Tsunami(1, 0, M-1);
    
    return 0;
}

 

以上是关于[BZOJ 4184] shallot 以时间为基底建线段树的主要内容,如果未能解决你的问题,请参考以下文章

「bzoj 4184: shallot」

[BZOJ4184]shallot

bzoj 4184: shallot (线段树维护线性基)

[bzoj4184]shallot

Bzoj 4184: shallot

BZOJ 4184 shallot 线性基+分治