bzoj 3166 [Heoi2013]Alo 可持久化字典树

来源:互联网 发布:淘宝开店怎么推广宣传 编辑:程序博客网 时间:2024/06/05 17:24

次大值可以用过二分加rmq方法求出,左右边求出后会形成两个区间,然后直接上可持久化字典树。

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cmath>using namespace std;const int maxn=50005;int root[maxn];int cnt;int fa[50];namespace  Trie{    int sum[maxn*32];    int ch[maxn*32][2];    void init(){        memset(ch,0,sizeof(ch));        memset(sum,0,sizeof(sum));    }    void insert(int pre,int no,int val){        for(int i=30;i>=0;i--){            ch[no][0]=ch[pre][0];            ch[no][1]=ch[pre][1];            sum[no]=sum[pre]+1;            int w=(val>>i)&1;            ch[no][w]=++cnt;            no=ch[no][w];            pre=ch[pre][w];        }        sum[no]=sum[pre]+1;    }    int query(int pre,int no,int val){        int s=0;        for(int i=30;i>=0;i--){            int w=(val>>i)&1;            if(sum[ch[no][w^1]]-sum[ch[pre][w^1]]>0){                s+=fa[i];                w=w^1;            }            no=ch[no][w];            pre=ch[pre][w];        }        return s;    }}int maxl[maxn][16];void S_table(int n){    int l = int(log((double)n)/log(2.0));    for (int j=1;j<=l;j++)    {        for (int i=1; i + (1 << (j-1) ) - 1 <=n;++i)        {            maxl[i][j] = max(maxl[i][j-1], maxl[i + (1 << (j-1) )][j-1]);        }    }}int rmq(int l, int r){    int k = int(log((double)(r-l+1))/log(2.0));    int a1 = max(maxl[l][k], maxl[r - (1<<k) + 1][k]);    return a1;}int a[maxn];int main(){    for(int i=0;i<=30;i++)fa[i]=1<<i;    int n;    cnt=0;    cin>>n;    for(int i=1;i<=n;i++){        scanf("%d",&a[i]);        root[i]=++cnt;        Trie::insert(root[i-1],root[i],a[i]);        maxl[i][0]=a[i];    }    S_table(n);    int ans=0;    for(int i=1;i<=n;i++){        int le=1,ri=i-1;        while(le<=ri){            int mid=(le+ri)/2;            if(rmq(mid,i-1)>a[i]) le=mid+1;            else ri=mid-1;        }        int l1=ri;        int l2=0;        if(ri>1){            le=1;            ri=l1-1;            while(le<=ri){                int mid=(le+ri)/2;                if(rmq(mid,l1-1)>a[i]) le=mid+1;                else ri=mid-1;            }            l2=ri;        }        le=i+1,ri=n;        while(le<=ri){            int mid=(le+ri)/2;            if(rmq(i+1,mid)>a[i]) ri=mid-1;            else le=mid+1;        }        int r1=le;        int r2=n+1;        if(r1<n){            le=r1+1,ri=n;            while(le<=ri){                int mid=(le+ri)/2;                if(rmq(r1+1,mid)>a[i]) ri=mid-1;                else le=mid+1;            }            r2=le;        }        if(l1>=1){            ans=max(ans,Trie::query(root[l2],root[r1-1],a[i]));        }        if(r1<=n){            ans=max(ans,Trie::query(root[l1],root[r2-1],a[i]));        }    }    cout<<ans<<endl;}


0 0
原创粉丝点击