左右两边的比i大的最近的两个值。然后可持久化字典树即可。
#include<bits/stdc++.h> using namespace std; int maxn=0,n,root[1600000],a[50010],cnt=0,l[1600000],r[1600000],p1[50010][25],p2[50010][25],sum[1600000],ans=0,pans=0,l1[50010],r1[50010],l2[50010],r2[50010]; void add(int &rt,int pre,int val,int id) { if(!rt)rt=++cnt; sum[rt]=sum[pre]+1; if(id<0)return; if(val&(1<<id)) { l[rt]=l[pre]; add(r[rt],r[pre],val,id-1); } else { r[rt]=r[pre]; add(l[rt],l[pre],val,id-1); } } void work(int L,int R,int val,int id) { if(id<0)return; if((1<<id)&val) { if(sum[l[R]]-sum[l[L]]) { pans|=(1<<id); work(l[L],l[R],val,id-1); } else work(r[L],r[R],val,id-1); } else { if(sum[r[R]]-sum[r[L]]) { pans|=(1<<id); work(r[L],r[R],val,id-1); } else work(l[L],l[R],val,id-1); } } int main() { //freopen("xf.in","r",stdin); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); maxn=max(maxn,a[i]); p1[i][0]=a[i]; p2[i][0]=a[i]; add(root[i],root[i-1],a[i],29); } int gl=log2(n)+2; for(int i=1;i<=gl;i++) { for(int j=1;j<=n;j++) { p1[j][i]=max(p1[j][i-1],p1[max(1,j-(1<<(i-1)))][i-1]); p2[j][i]=max(p2[j][i-1],p2[min(n,j+(1<<(i-1)))][i-1]); } } for(int i=1;i<=n;i++) { int w=i-1; if(i!=1&&p1[w][gl]>a[i]) { for(int j=gl;j>=0;j--) { if(p1[w][j]<=a[i]) { w-=(1<<j); } } l1[i]=w; if(w!=1&&p1[w-1][gl]>a[i]) { w=w-1; for(int j=gl;j>=0;j--) { if(p1[w][j]<=a[i]) { w-=(1<<j); } } l2[i]=w; } } w=i+1; if(i!=n&&p2[w][gl]>a[i]) { for(int j=gl;j>=0;j--) { if(p2[w][j]<=a[i]) { w+=(1<<j); } } r1[i]=min(w,n); if(w!=n&&p2[w+1][gl]>a[i]) { w=w+1; for(int j=gl;j>=0;j--) { if(p2[w][j]<=a[i]) { w+=(1<<j); if(w>n)break; } } r2[i]=min(n,w); } } } for(int i=1;i<=n;i++) { if(a[i]==maxn)continue; pans=0; if(l1[i]) { int ll=0,rr=n; if(r1[i])rr=r1[i]-1; if(l2[i])ll=l2[i]; work(root[ll],root[rr],a[i],29); } ans=max(ans,pans); pans=0; if(r1[i]) { int ll=0,rr=n; if(r2[i])rr=r2[i]-1; if(l1[i])ll=l1[i]; work(root[ll],root[rr],a[i],29); } ans=max(ans,pans); } printf("%d ",ans); return 0; }