最大异或和(xor)

最大异或和(xor)

最大异或和(xor)

题目描述

 

给定一个非负整数序列{a},初始长度为N。

有M个操作,有以下两种操作类型:

1、A x:添加操作,表示在序列末尾添加一个数x,序列的长度N+1。

2、Q l r x:询问操作,你需要找到一个位置p,满足l<=p<=r,使得:

a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少。

 

输入

 

第一行包含两个整数N,M,含义如问题描述所示。

第二行包含N个非负整数,表示初始的序列A。

 

接下来M行,每行描述一个操作,格式如题面所述。

 

 

 

输出

 

假设询问操作有T个,则输出应该有T行,每行一个整数表示询问的答案。

 

 

 

样例输入

5 5
2 6 4 3 6 
A 1
Q 3 5 4
A 4
Q 5 7 0
Q 3 6 6

样例输出

4
5
6

提示

 

本题共有10个测试点,每个测试点10分。

对于测试点1-2,N,M<=5。

对于测试点3-7,N,M<=80000。

对于测试点8-10,N,M<=300000。

其中测试点1, 3, 5, 7, 9保证没有修改操作。

对于100%的数据,0<=a[i]<=10^7。


solution

 考虑异或满足前缀相减。

答案=1~an~x的异或和异或1~i的异或和

 前一部分是定值。

后一部分,我们对于每一个前缀都加进trie树,在trie上贪心即可。

建议写递归写法,注意边界。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cmath>
 7 using namespace std;
 8 int n,m,rt[600005],now,cnt;
 9 struct trie{
10     int ch[2],v;
11 }tr[600005*26];
12 void ins(int k,int la,int v){
13     for(int i=25;i>=0;i--){
14         tr[k].v=tr[la].v+1;
15         bool t=((v&(1<<i))>0);
16         tr[k].ch[!t]=tr[la].ch[!t];
17         tr[k].ch[t]=++cnt;
18         k=tr[k].ch[t],la=tr[la].ch[t];
19     }
20     tr[k].v=tr[la].v+1;
21 }
22 int ask(int k,int la,int v){
23     int ans=0;
24     for(int i=25;i>=0;i--){
25         bool t=((v&(1<<i))>0);t=(!t);
26         int s1=tr[k].ch[t],s2=tr[la].ch[t];
27         if(tr[s1].v>tr[s2].v){
28             ans+=(1<<i);k=s1;la=s2;
29         }
30         else{
31             k=tr[k].ch[!t],la=tr[la].ch[!t];
32         }
33     }
34     return ans;
35 }
36 int main()
37 {
38     cin>>n>>m;
39     for(int i=1,t;i<=n;i++){
40         scanf("%d",&t);
41         rt[i]=++cnt;
42         now^=t;ins(rt[i],rt[i-1],now);
43     }
44     int rn=n;
45     for(int i=1,t,a,b;i<=m;i++){
46         char c;scanf(" %c",&c);
47         if(c=='A'){
48             scanf("%d",&t);rn++;rt[rn]=++cnt;
49             now^=t;ins(rt[rn],rt[rn-1],now);
50         }
51         else {
52             scanf("%d%d%d",&a,&b,&t);t^=now;
53             if(b==1)printf("%d\n",t);
54             else {
55                 //cout<<rt[b-1]<<' '<<rt[a-2]<<endl;
56                 printf("%d\n",ask(rt[b-1],a-2>0?rt[a-2]:0,t));   
57             }
58         }
59     }
60     return 0;
61 }
View Code

 

posted @ 2019-02-17 21:12 liankewei123456 阅读( ...) 评论( ...) 编辑 收藏
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值