NEUOJ711 异星工厂 字典树+贪心
Posted shuguangzw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NEUOJ711 异星工厂 字典树+贪心相关的知识,希望对你有一定的参考价值。
题意:你可以收集两个不相交区间的权值,区间权值是区间异或,问这两个权值和最大是多少
分析:很多有关异或求最大的题都是利用01字典树进行贪心,做这个题的时候我都忘了。。。最后是看别人代码的时候才想起来这个套路
l[i],记录,从 1 到 i 里 最大的异或区间权值,
r[i], 记录,从 i 到 n 里 最大的异或区间权值
这样两轮插入,然后查询贪心就行了,插入的是前缀和后缀的异或2进制序列,从大的开始(贪心)
注:吐槽,其实都是套路,异或和求最大,往往要利用字典树进行贪心
#include <cstdio> #include <iostream> #include <ctime> #include <vector> #include <cmath> #include <map> #include <queue> #include <algorithm> #include <cstring> using namespace std; typedef long long LL; const int N=3e6+5; const int M=1e5+5; const int INF=0x3f3f3f3f; struct Node{ int nex[2]; }p[N+M]; int cnt; int newnode(){ ++cnt; p[cnt].nex[0]=p[cnt].nex[1]=-1; return cnt; } int x[M],a[M]; void insert(int pos){ int now=0; for(int i=30;i>=0;--i){ int cur=(x[pos]&(1<<i))>0?1:0; if(p[now].nex[cur]==-1) p[now].nex[cur]=newnode(); now=p[now].nex[cur]; } } int getmax(int pos){ int now=0,ret=0; for(int i=30;i>=0;--i){ int cur=(x[pos]&(1<<i))>0?1:0; if(p[now].nex[cur^1]!=-1){ ret+=(1<<i); now=p[now].nex[cur^1]; } else now=p[now].nex[cur]; } return ret; } int l[M],r[M]; int main() { int n; while(~scanf("%d",&n)){ cnt=-1;newnode(); insert(0); for(int i=1;i<=n;++i){ scanf("%d",&a[i]); x[i]=(x[i-1]^a[i]); l[i]=max(getmax(i),l[i-1]); insert(i); } r[n+1]=x[n+1]=0; cnt=-1;newnode(); insert(n+1); for(int i=n;i;--i){ x[i]=(x[i+1]^a[i]); r[i]=max(getmax(i),r[i+1]); insert(i); } LL ret=0; for(int i=1;i<n;++i) ret=max(ret,1ll*l[i]+1ll*r[i+1]); printf("%lld\\n",ret); } return 0; }
以上是关于NEUOJ711 异星工厂 字典树+贪心的主要内容,如果未能解决你的问题,请参考以下文章