BZOJ 3166: [Heoi2013]Alo|可持久化Trie树

来源:互联网 发布:sql界面默认值或绑定 编辑:程序博客网 时间:2024/06/03 18:30

枚举次大值,可以发现他可以任意抑或的数肯定在一个区间L,R
L为这个数左边第二个大于他的数的位置,R也同理,然后用可持久化Trie树直接贪心查找抑或的最大值。
然后LR怎么求呢??
诶..我们发现可能数据是随机的,所以暴力就可以过掉了..想要快一点可以用set水一水

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<queue>#include<vector>#include<set>#include<map>#include<algorithm>#include<iostream>#define N 50005using namespace std;int sc(){    int i=0; char c=getchar();    while(c>'9'||c<'0')c=getchar();    while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();    return i;}int root[N],ch[N*50][2],sum[N*50];int cnt,a[N],n,mx,ans;void add(int pre,int &x,int v,int k){    if(!x)x=++cnt;    sum[x]=sum[pre]+1;    if(!k)return;    if(v&k)        ch[x][0]=ch[pre][0],        add(ch[pre][1],ch[x][1],v,k>>1);    else        ch[x][1]=ch[pre][1],        add(ch[pre][0],ch[x][0],v,k>>1);}int ask(int L,int R,int v){    int ans=0,k=1<<30;    while(k)    {        bool e=!(k&v);        if(sum[ch[R][e]]-sum[ch[L][e]])            R=ch[R][e],L=ch[L][e],ans+=k;        else            L=ch[L][!e],R=ch[R][!e];        k>>=1;    }    return ans;}   int main(){    n=sc();    for(int i=1;i<=n;i++)    {        mx=max(mx,a[i]=sc());        add(root[i-1],root[i],a[i],1<<30);    }    a[0]=a[n+1]=mx+1;    for(int i=1;i<=n;i++)        if(a[i]!=mx)        {            int l=i,r=i;            while(a[l-1]<a[i])l--;            while(a[r+1]<a[i])r++;            int L=max(1,l-1);            int R=min(n,r+1);            while(a[L-1]<a[i])L--;            while(a[R+1]<a[i])R++;            ans=max(ans,ask(root[L-1],root[R],a[i]));        }    cout<<ans;    return 0;}
0 0
原创粉丝点击