luoguP4098 「HEOI2013」 ALO

To provide a moresimpleAgricultural practices code:

First approach is obvious: a fixed location next smallest value of \ (i \) , to find the next smallest value indeed all sections of this number, then be persistent \ (01Trie \) to find these intervals can be set on and press bit greedy

Conclusion: If \ (PR \) such that \ ([i, pr] \ ) interval there are at least two greater than the number \ (a_i \) the minimum position, \ (PL \) such that \ ([pl, i ] \) interval there are at least two greater than the number \ (a_i \) maximum position, then \ ([pl, pr] \ ) all numbers in the interval can be used and \ (a_i \) exclusive or update answers

So we first give again swept in a monotonous stack \ (I \) is about greater than a first \ (a_i \) position \ (QL, QR \) , after the \ ([1, ql-1 ] \) and \ ( [qr + 1, n] \ ) within two minutes, to find the closest \ (I \) and satisfy \ (max ([midl, ql -1] \ text {or} [qr + 1, midr])> a_i \) position \ (midl, midr \) is also desired in \ (pl, pr \)

Interval maximum value with \ (ST \) table maintenance, complexity \ (O (nlogn) \) , while, if, instead of using the same first half stack may be simply a monotonic Treatment \ (K \) small problem

\(code:\)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
const int maxn=5e4+5,D=29;
int n,root[maxn],tot,a[maxn],ans;
//29
struct Trie
{
    struct node{int ch[2],siz;}t[15000000];
    public:
    void upd(int &rt,int pre,int x,int d)
    {
        t[rt=++tot]=t[pre];++t[rt].siz;
        if(d<0)return;
        int k=(x>>d)&1;
        upd(t[rt].ch[k],t[pre].ch[k],x,d-1);
    }
    int qry(int rt,int pre,int x,int d)
    {
        if(d<0)return 0;
        int k=!((x>>d)&1);
        if(t[t[rt].ch[k]].siz>t[t[pre].ch[k]].siz)return (1<<d)|qry(t[rt].ch[k],t[pre].ch[k],x,d-1);
        return qry(t[rt].ch[k^1],t[pre].ch[k^1],x,d-1);
    }
}T;
int lh[maxn],rh[maxn];
stack<int>s;
int st[maxn][16],H=15,lg[maxn];
int mx(int l,int r)
{
    int k=lg[r-l+1];
    return max(st[l][k],st[r-(1<<k)+1][k]);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)scanf("%d",&a[i]),st[i][0]=a[i];
    for(int i=1;i<=n;++i)T.upd(root[i],root[i-1],a[i],D);
    for(int k=1;k<=H;++k)
        for(int i=1;i+(1<<k)-1<=n;++i)
            st[i][k]=max(st[i][k-1],st[i+(1<<(k-1))][k-1]);
    for(int i=2;i<=n;++i)lg[i]=lg[i>>1]+1;
    for(int i=1;i<=n;++i)
    {
        while(!s.empty()&&a[i]>a[s.top()])rh[s.top()]=i,s.pop();
        s.push(i);
    }
    while(!s.empty())rh[s.top()]=n+1,s.pop();
    for(int i=n;i>=1;--i)
    {
        while(!s.empty()&&a[i]>a[s.top()])lh[s.top()]=i,s.pop();
        s.push(i);
    }
    while(!s.empty())lh[s.top()]=0,s.pop();
    for(int i=1;i<=n;++i)
    {
        int l=rh[i]+1,r=n,mid,anss=n+1;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if(mx(rh[i]+1,mid)>a[i])anss=mid,r=mid-1;
            else l=mid+1;
        }
        rh[i]=anss;
        l=1,r=lh[i]-1,anss=0;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if(mx(mid,lh[i]-1)>a[i])anss=mid,l=mid+1;
            else r=mid-1;
        }
        lh[i]=anss;
        ans=max(ans,T.qry(root[rh[i]-1],root[lh[i]],a[i],D));
    }
    printf("%d\n",ans);
}

Guess you like

Origin www.cnblogs.com/study-ysj/p/11229159.html