【Bzoj4184】 shallot——时间分治+线性基

28 篇文章 0 订阅
11 篇文章 0 订阅
Time Limit: 30 SecMemory Limit: 128 MB

Description

小苗去市场上买了一捆小葱苗,她突然一时兴起,于是她在每颗小葱苗上写上一个数字,然后把小葱叫过来玩游戏。

每个时刻她会给小葱一颗小葱苗或者是从小葱手里拿走一颗小葱苗,并且
让小葱从自己手中的小葱苗里选出一些小葱苗使得选出的小葱苗上的数字的异或和最大。
这种小问题对于小葱来说当然不在话下,但是他的身边没有电脑,于是他打电话给同为Oi选手的你,你能帮帮他吗?
你只需要输出最大的异或和即可,若小葱手中没有小葱苗则输出0。

Input

第一行一个正整数n表示总时间;第二行n个整数a1,a2…an,若ai大于0代表给了小葱一颗数字为ai的小葱苗,否则代表从小葱手中拿走一颗数字为-ai的小葱苗。

Output

输出共n行,每行一个整数代表第i个时刻的最大异或和。

Sample Input

6

1 2 3 4 -2 -3

Sample Output

1

3

3

7

7

5

HINT

N<=500000,Ai<=2^31-1
和QAQ巨一起切的题,有时间补题解

#include<vector>
#include<map>
#include<stack>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn = 512345;

vector<int> oper[maxn * 2];

#define root 1,n
#define lson l,m
#define rson m+1,r
#define Mid int m = (l + r) >> 1
#define Now int l,int r

int ID(int l, int r) {  
    return l + r | (l != r);  
}
void insert(Now,int il,int ir,int v){
    //printf("ins lr = %d %d ilir = %d %d v = %d\n",l,r,il,ir,v);
    int o = ID(l,r);
    if(il <= l && r <= ir){
        oper[o].push_back(v);
        return;
    }
    Mid;
    if(il <= m) insert(lson,il,ir,v);
    if(m+1<=ir) insert(rson,il,ir,v);
}

struct Info{
    int bas[32];
    void init(){
        memset(bas,0,sizeof(bas));
    }
    void add(int x){
        for(int i = 31;i>=0;i--) {
            if((x>>i)&1) {
                if(bas[i]) x^=bas[i];
                else {
                    bas[i]=x;
                    break;
                }
            }
        }
    }
    int que(){
        int ans = 0;
        for(int i = 31;i>=0;i--) ans = max(ans,ans^bas[i]);
        return ans;
    }
    void cpy(Info & v){
        for(int i = 0 ; i <= 31; i ++){
            bas[i] = v.bas[i];
        }
    }
}info[50];
int nex[50],head,tail;
void init(){
    head = 0,tail = 50-1;
    for(int i = 0 ; i < 50 ; i ++)
        nex[i] = i + 1;
    nex[tail] = -1;
}
int newInfo(){
    info[head].init();
    int ret = head;
    head = nex[head];
    return ret;
}
void deleteInfo(int st){
    nex[tail] = st;
    nex[st] = -1;
    tail = st;
}

stack<int> S;
void dfs(Now){
    int o = ID(l,r),st = newInfo();
    info[st].cpy(info[S.top()]);
    S.push(st);
    for(vector<int>::iterator it = oper[o].begin(); it != oper[o].end();it++) 
        info[st].add(*it);
    if(l == r) printf("%d\n",info[st].que());
    else{
        Mid;
        dfs(lson),dfs(rson);
    }
    deleteInfo(st);
    S.pop();
}

map<int,int> M;

int main(){
    int n;
    scanf("%d",&n);
    int x;
    for(int i = 1; i <= n ; i ++){
        scanf("%d",&x);
        if(x > 0) M[x] = i;
        else{
            insert(root,M[-x],i-1,-x);
            M.erase(-x);
        }
    }
    for(map<int,int>::iterator ite = M.begin();ite != M.end();ite++) 
        insert(root,ite->second,n,ite->first);
    init();
    int rot = newInfo();
    S.push(rot);
    dfs(root);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值