码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-07-30 23:51:05      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:区间   cstring   --   reg   har   freopen   div   dfs   include   

题意

  给定时长 $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 以时间为基底建线段树

标签:区间   cstring   --   reg   har   freopen   div   dfs   include   

原文地址:http://www.cnblogs.com/Sdchr/p/7260750.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!