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

Bzoj 4184: shallot

时间:2018-02-23 22:20:09      阅读:195      评论:0      收藏:0      [点我收藏+]

标签:val   电脑   zoj   push   直接插入   sizeof   线段   clu   需要   

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

 

又是一道线性基...但是这次加了删除..好像不可做?嗯...这节课不是在讲数据结构吗...所以...线段树上维护线性基啊...时间作为叶子节点,如果是插入的话就直接插入就行了,删除的话去找上一个插入的地方,把上次插入的地方改成0,然后每次线段树单点修改,回去的时候区间合并,把每个节点维护的线性基合并起来。总体复杂度大概是O(nlog^2n),时间要注意一下(50w的nlog^2n...呃...我一开始没看空间MLE了...)

下面是代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<vector>
 6 #include<map>
 7 using namespace std;
 8 vector<int>tree[2000010];
 9 map<int,int>str,num;
10 int in[500010],st,ed,val,a[31];
11 void change(int l,int r,int pos){
12     if(st<=l&&r<=ed){
13         tree[pos].push_back(val);
14         return;
15     }
16     int mid=(l+r)/2,lson=pos*2,rson=pos*2+1;
17     if(st<=mid) change(l,mid,lson);
18     if(mid<ed) change(mid+1,r,rson);
19     return;
20 }
21 void merge(int pos){
22     for(unsigned i=0;i<tree[pos].size();i++){
23         for(int j=30;j>=0;j--){
24             if((tree[pos][i]&(1<<j))==0) continue;
25             if(a[j]==0){
26                 a[j]=tree[pos][i];
27                 break;
28             }
29             tree[pos][i]^=a[j];
30         }
31     }
32     return;
33 }
34 void find(int l,int r,int pos){
35     int ls[31],mg[31];
36     memcpy(ls,a,sizeof(ls));
37     merge(pos);
38     memcpy(mg,a,sizeof(mg));
39     if(l==r){
40         int i,ans=0;
41         for(i=30;i>=0;i--) ans=max(ans,ans^a[i]);
42         printf("%d\n",ans);
43         return;
44     }
45     int mid=(l+r)/2,lson=pos*2,rson=pos*2+1;
46     find(l,mid,lson);
47     memcpy(a,mg,sizeof(a));
48     find(mid+1,r,rson);
49     memcpy(a,ls,sizeof(a));
50     return;
51 }
52 int main()
53 {
54     int n,i;
55     scanf("%d",&n);
56     for(i=1;i<=n;i++){
57         scanf("%d",&in[i]);
58         if(in[i]>0){
59             if(str.count(in[i])==false){
60                 str[in[i]]=i;
61                 num[in[i]]=0;
62             }
63             num[in[i]]=num[in[i]]+1;
64         }
65         else{
66             in[i]=-in[i];
67             num[in[i]]=num[in[i]]-1;
68             if(num[in[i]]==0){
69                 st=str[in[i]];
70                 ed=i-1;
71                 val=in[i];
72                 change(1,n,1);
73                 str.erase(in[i]);
74             }
75         }
76     }
77     for(i=1;i<=n;i++){
78         if(str.count(in[i])){
79             st=str[in[i]];
80             ed=n;
81             val=in[i];
82             change(1,n,1);
83         }
84     }
85     find(1,n,1);
86     return 0;
87 }

 

Bzoj 4184: shallot

标签:val   电脑   zoj   push   直接插入   sizeof   线段   clu   需要   

原文地址:https://www.cnblogs.com/pncbf/p/8463385.html

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