BZOJ 4260 Codechef REBXOR trie树+树状数组
来源:互联网 发布:阿里云架设代理服务器 编辑:程序博客网 时间:2024/04/30 16:08
Description
Input
输入数据的第一行包含一个整数N,表示数组中的元素个数。
第二行包含N个整数A1,A2,…,AN。
Output
输出一行包含给定表达式可能的最大值。
Sample Input
5
1 2 3 1 2
1 2 3 1 2
Sample Output
6
HINT
满足条件的(l1,r1,l2,r2)有:(1,2,3,3),(1,2,4,5),(3,3,4,5)。
对于100%的数据,2 ≤ N ≤ 4*105,0 ≤ Ai ≤ 109。
传送门
好题……不怎么难。。
先考虑只取一段的情况,
首先对原来的数组作xor的前缀和。
我们知道xor也是满足这样的性质的:
a[x]^a[x+1]^……^a[y]=sum[x-1]^sum[y]
我们可以枚举连续序列的尾部y,那么也就是说要找出一个x,
使得sum[x-1]^sum[y]最大。
xor不像加法或者减法,对于不同的数字,和它异或起来大的数字是不同的。
这个时候去考虑一下二进制方面,
假如sum[y]=0011(二),那么sum[x-1]尽量是谁呢?
当然是1100(二)了。
每一位都尽量找不同的那一位即可。。
那假如没有sum[x-1]=1100呢?1000和0100谁更优呢。。
二进制的从后往前第x位带有2^(x-1)的权值,
也就是011111<100000...
所以我们从高位到低位,能有对应的就选择这个对应的,不然只好选择另一个。
这个过程可以用trie树实现,每个节点连向儿子有两种边,一种是0,一种是1;
比如走1的边,意义就是二进制上这一位是1.
每次处理完sum[x],就把sum[x]转化为二进制插入到trie里就好了。
假如一个节点u,sum[y]的目前位置的二进制位数字是p,
如说u的son[p^1]非空,那么u走向son[p^1],不然u走向son[p],
最后把数字加起来,return的就是和sum[y]xor最优的了。。
-> v ->这个地方竟然说了这么多……
那题目要求两段不重复的,要怎么办呢?
首先对于第一段,枚举一个结尾的话,很容易就用刚才的方法求出最优值了;
而对于第二段,如果是枚举结尾i,我们可以发现不一定是刚才的方法最优了……
因为我们要找的是{以k结尾的第一段的最大值+sum[i] xor sum[j-1]}
可以用下图来表示:
可以发现这个时候就有点不可做了……
但是我们可以发现:第一段枚举结尾来确定,因为第一段的之前的部分对后面没有了影响;
很容易地,能够想到优化:
枚举第二段的开头,也就是图中的j,
然后在trie树里,我们可以直接找出来一个最优的sum[i](因此我们要从尾往头线扫);
而对于F[k],我们仍然是取最大的,这个F[k]的最大值我们用树状数组维护即可。
#include<bits/stdc++.h>using namespace std;const int N=400005, MAXLEN=31;int n,len,cnt;int ejz[MAXLEN+5],a[N],sum[N];int tr[N],f[N],trie[N*MAXLEN][2];void update(int x,int y){ for (int i=x;i<=n;i+=i&-i) tr[i]=max(tr[i],y);}int getmaxf(int x){ int y=0; for (int i=x;i;i-=i&-i) y=max(y,tr[i]); return y;}void jzzh(int x){ len=0; while (x) ejz[++len]=(x&1),x>>=1; int tmp=len+1; for (int i=tmp;i<=MAXLEN;i++) ejz[i]=0; len=MAXLEN;}void insert(int x){ int now=0; jzzh(x); for (int i=len;i;i--) if (trie[now][ejz[i]]) now=trie[now][ejz[i]]; else now=trie[now][ejz[i]]=++cnt;}int get_xor_max(int x){ int now=0,an=0; jzzh(x); for (int i=len;i;i--){ if (trie[now][!ejz[i]]) now=trie[now][!ejz[i]],an+=(!ejz[i])*(1<<(i-1)); else now=trie[now][ejz[i]],an+=ejz[i]*(1<<(i-1)); } return an;}void Pre(){ sum[0]=0; for (int i=1;i<=n;i++) sum[i]=sum[i-1]^a[i]; cnt=0,insert(0); f[1]=sum[1],insert(sum[1]); for (int i=2;i<=n;i++){ f[i]=sum[i]^get_xor_max(sum[i]); insert(sum[i]); } for (int i=1;i<=n;i++) update(i,f[i]);}void solve(){ cnt=0; memset(trie,0,sizeof(trie)); insert(sum[n]); int ans=0; for (int j=n-1;j>1;j--){ int tmp=sum[j]^get_xor_max(sum[j]); ans=max(ans,getmaxf(j)+tmp); insert(sum[j]); } printf("%d\n",ans);}int main(){ scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); Pre(); solve(); return 0;}
阅读全文
0 0
- BZOJ 4260 Codechef REBXOR trie树+树状数组
- BZOJ 4260: Codechef REBXOR|Trie树
- 【BZOJ 4260】 Codechef REBXOR|trie
- bzoj 4260: Codechef REBXOR Trie
- BZOJ 4260 Codechef REBXOR 可持久化Trie树
- 【BZOJ 4260】Codechef REBXOR 可持久化trie树
- BZOJ 4260 Codechef REBXOR 01Trie
- 4260: Codechef REBXOR trie
- bzoj 4260 Codechef REBXOR
- bzoj 4260: Codechef REBXOR
- [BZOJ]4260: Codechef REBXOR 可持久化Trie
- BZOJ 4260: Codechef REBXOR 字典树
- 【bzoj4260】 Codechef REBXOR trie树
- 【bzoj4260】【Codechef REBXOR】【trie】
- BZOJ4260 Codechef REBXOR trie
- Codechef REBXOR(01Trie)
- bzoj 4260 Codechef REBXOR(前缀和+01字典树)
- bzoj 4260: Codechef REBXOR(01字典树)
- 分布式服务:spring mvc +mybatis + Dubbo+Zookeeper+Proxy+Restful
- BZOJ 4195 [Noi2015]程序自动分析 并查集
- JEESZ分布式框架安装和使用
- 李さんは中国人です
- NTU-Coursera机器学习:VC Bound和VC维度
- BZOJ 4260 Codechef REBXOR trie树+树状数组
- POJ 1308 && HDU 1325 Is It A Tree?(并查集)
- 史上最全最强SpringMVC详细示例实战教程
- 怎么申请微信支付服务商-微信公众号使用教程29
- 怎么认证微信支付服务商-微信公众号使用教程30
- django
- Java生产者消费者简易版
- [转]AWR解读技巧-OLTP
- okhttp异步请求和同步请求